-pthread propagation

Daniel Eischen deischen at freebsd.org
Wed Apr 1 17:31:25 PDT 2009


On Thu, 2 Apr 2009, Dmitry Marakasov wrote:

> Hi!
>
> I have a question about -pthread. Imagine the situation where one port
> installs shared library that uses threads, and other port links with
> this library. A question: should the second port explicitely add
> -pthread to linker flags?

Yes.

> For example, graphics/ilmbase is built with pthread support by default,
> but it's shared libraries are not linked with -pthread:
>
> % ldd /usr/local/lib/libIlmThread.so
> /usr/local/lib/libIlmThread.so:
> 	libIex.so.6 => /usr/local/lib/libIex.so.6 (0x2819c000)
> 	libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x28300000)
> 	libm.so.5 => /lib/libm.so.5 (0x281ad000)
> 	libc.so.7 => /lib/libc.so.7 (0x2808b000)
> 	libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x281c6000)
>
> no libthr.so mention. Thus,
>
> % gcc helloworld.cc -lIlmThread -L/usr/local/lib
> /usr/local/lib/libIlmThread.so: undefined reference to `pthread_create'
>
> I assume this should be fixed in ilmbase instead of all dependent ports
> (for example, graphics/nvidia-texture-tools and graphics/devil, which
> supports the former), am I right? Btw, libIlmThread.la _does_ have
> -pthread in dependency_libs.

Yes, all ports that use libraries that create threads on
their behalf should use -pthread.

> However, I've encountered situations where linking with library
> linked with -pthread will succeed, but the resulting binary will not
> be broken. Example is games/battletanks:

This is probably because libc contains some simple thread
wrappers (mostly lock related stuff).  They go unused unless
a thread is created (and libthr is explicitly brought in),
in which case those wrappers are overridden by libthr.

> When built as is (note that it has ${PTHREAD_LIBS} explicitely added to
> LDFLAGS), it runs without problems. However, if you remove
> ${PTHREAD_LIBS}, it'll still build successfully, but won't run:
>
> % bt
> [03:04:45.449][src/main.cpp:44]	 [notice] starting up... version: 5800 beta
> [03:04:45.449][src/main.cpp:46]	 [notice] mem avail: -1 mb
> terminate called after throwing an instance of '__gnu_cxx::__concurrence_lock_error'
>  what():  __gnu_cxx::__concurrence_lock_error
> [1]    58620 abort (core dumped)  bt
>
> I think that's linked with static variable initialization - it should
> be protected with a mutex in threaded environment, but it doesn't happen
> correctly when linking without -pthread, even if with -lthr.

It is possible for a library to be thread-aware and thread-safe.
In this case it can play pragma weak games with "pthread_create"
and only use locks if pthread_create resolves to a non-null
pointer.

> I'll be really grateful if someone explains what really happens when
> using -lpthread, and what happens in the above mentioned error case
> (cc'ing hackers@).
>
> So should -pthread be forced in ldflags
> 1) Only in ports that explicitely use threads
> 2) In all ports that link with -lthr implicitely, including through
> other ports?

It depends, libraries can be made thread-safe/aware as
above, and both threaded and non-threaded applications
can link with them just fine.  Assuming those libraries
are smart about how they use the locking mechanisms,
and never use them unless they know that "pthread_create"
is present (or some other symbol not present in libc,
but present in libthr).

But for libraries that create threads, applications must
also link with -pthread (or -lpthread).

If you can understand it, you can see
src/contrib/gcc/gthr-posix.h for how libgcc is
thread-aware.  A comment from that file:

   /* On Solaris 2.6 up to 9, the libc exposes a POSIX threads
      interface even if -pthreads is not specified.  The
      functions are dummies and most return an error value.
      However pthread_once returns 0 without invoking the routine
      it is passed so we cannot pretend that the interface is
      active if -pthreads is not specified.  On Solaris 2.5.1,
      the interface is not exposed at all so we need to play the
      usual game with weak symbols.  On Solaris 10 and up, a
      working interface is always exposed.  On FreeBSD 6 and
      later, libc also exposes a dummy POSIX threads interface,
      similar to what Solaris 2.6 up to 9 does.  FreeBSD >=
      700014 even provides a pthread_cancel stub in libc, which
      means the alternate __gthread_active_p below cannot be used
      there. */

-- 
DE


More information about the freebsd-ports mailing list