2009/10/13 Michael Matz email@example.com:
On Mon, 12 Oct 2009, Cristian Morales Vega wrote:
Looking to some .pc (pkg-config) files I though about this... -pthread can make sure that libpthread is linked in before libc, ok. But what happens if I compile a library with -pthread and then use it from a program that doesn't uses libpthread? Wouldn't in this case the library use the symbols from libc?
And this is exactly what happens sometimes. A program is not thread-aware, loads some plugin which does use threads (and is linked against libpthread), et voila, you get a heap of interesting and hard to diagnose locking issues, usually resulting in dead locks of the program.
I though that this could be fixed if every library that uses libpthread adds -pthread to the CFlags in its .pc file (so the program will link against libpthread even if it doesn't uses it). But if I'm using --as-needed this would not work.
Right. It usually works to have it only in some strategic libs because most programs aren't multi-threaded I guess. See below.
You said: "Other things (gcc .spec files) make sure that libpthread is linked in _before_ libc when -pthread is given". But this doesn't solves the problem at runtime. There is also any special exception in ld.so so libpthread is always loaded before libc?
Even if libpthread is only used by a library deep in the dependency tree and not in the main binary?
Now thinking about this, you seem to have a point. A grave point even. If the application itself isn't linked to libpthread (but to libc, which all of them are) then libc will _always_ come before libpthread in symbol search order, for all further symbol lookups. Even from dependency shared libs. So in effect the thread-aware versions will never be used in that scenario. I just verified this behaviour (lib against libpthread, app against lib but not libpthread, lib uses one of the double symbols, and voila, the ones from libc are picked up, not the ones from libpthread). Uhoh.
Hmm. I think we're screwed. Applications itself, when there's even a slightest chance of some of its libraries using threads plus the problematic libc functions, must be linked against libpthread; without --as-needed getting rid of it. It's not enough if some core toolkit library links against libpthread, it must be the top-level app.
I guess we're not seeing much more of these problems, because if threads are used at all, then probably not the problematic libc functions, or if then not in contexts where it matters. A bit fragile to rely upon this, as it's non-trivial to define the problematic set. It's not as easy as those symbols which are exported by libc as well as by libpthread. E.g. __open and __open64 in both libraries do the same thing. But e.g. flockfile is indeed a noop in libc, and does locking in libpthread.
Couldn't this be fixed through symbol versioning? Note that what I know about this is what I have just read and some quick tests.
Right now both libc and libpthread export "open@@GLIBC_2.0". Could not libpthread instead (or also) export "open@@PTHREAD_2.9"?