is pthread
in glibc.so
implemented by weak symbol to provide pthread
stub functions?
I know there is pthread.so
to provide the functions similar with pthread
in glibc.so
somebody said pthread
in glibc
provide stub only and will be replace when explicit linking to lpthread
.
So my question is how to support it? using weak symbol or other tech?
is libssl
similar with pthread
in glibc
?
Yes, glibc uses a stub implementation of various pthread functions, so that single threaded programs do not have to waste cycles doing things like locking and unlocking mutexes, and yet do not have to link to a different C library (like what is done in the Microsoft world, for instance).
For instance, according to POSIX, every time you call fputc(ch, stream)
, there is mutex lock and unlock. If you don't want that, you call fputc_unlocked
. But when you do that, you're using a POSIX extension related to threading; it's not an appropriate workaround for programs that don't use POSIX or don't use the threading API.
The overriding of the stub pthread functions with the real ones (in the dynamic glibc) is not based on weak symbols. The shared library mechanism makes it possible to override non-weak definitions.
Weak symbols are a mechanism which allows for symbol overriding under static linking.
If you want a source for the above statement, here it is:
"Note that a definition in a DSO being weak has no effects. Weak definitions only play a role in static linking." [Ulrich Drepper, "How To Write Shared Libraries"].
If you run nm
on the static glibc on your system (if you have one), libc.a
, you will note that functions like pthread_mutex_lock
are marked weak. In the dynamic version, libc.so.<whatetever>
, the functions are not marked weak.
Note: you should use nm -D
or nm --dynamic
to look at the symbols in a shared library. nm
will not produce anything on a shared library that is stripped. If it does, you're looking at the debug symbols, not the dynamic symbols.
See this SO answer. Several techniques can be used to allow the same symbol to be defined in multiple libraries against which a program is being linked, depending on whether dynamic or static linking is being used.
Symbol Interposition. When dynamic linking, if a symbol is defined in multiple libraries, then the linker will use the first version it finds (unless the symbols is internal, hidden or protected; see this blog article for a description of that)
Weak Objects. When static linking, if the linker finds two symbols of the same name, and one is a 'weak' reference, then the linker will use the non-weak reference.
Symbol versioning may also play a role.
In almost all cases, programs are dynamically linked to libc.
You can see the order in which the libs will be loaded using ldd:
$ ldd simple_pthread
linux-vdso.so.1 => (0x00007fffaddff000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007fa13a474000)
libc.so.6 => /lib64/libc.so.6 (0x00007fa13a0e0000)
/lib64/ld-linux-x86-64.so.2 (0x00007fa13a6a0000)
Here you can see that libpthread is before libc in the linking order. This is almost always going to be the case; libc is always linked last using default compiler options.
So, a program which is linked against libpthread will use the pthread versions of these symbols, since they are encountered first in the linking order.
If you are still unsure, starting your program with the environment variable LD_DEBUG set to 'bindings' will show the actual symbol bindings that are occurring.
If you are using static linking, you would be linking against libc.a instead of libc.so. You can use 'nm' to list details of the symbol. Weak symbols have a 'W' or 'w' for their type.
(Credit to @Kaz for pointing out that weak symbols to not affect dynamic linking).