Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

-pthread, -lpthread and minimal dynamic linktime dependencies

This answer suggest -pthread is preferable to -lpthread because predefined macros.

Empirically, -pthread gives me only one extra macro: #define _REENTRANT 1 and it also appears to force libpthread.so.0 as a dynamic linktime dependency.

When I compile with -lpthread, that dependency is only added if I actually call any of the pthread functions.

This is preferably to me, because then I wouldn't have to treat multithreaded programs differently in my build scripts.

So my question is, what else is there to -pthread vs -lpthread and is it possible to use use -pthread without forcing said dynamic linktime dependency?

Demonstration:

$ echo 'int main(){ return 0; }' | c gcc -include pthread.h -x c - -lpthread && ldd a.out | grep pthread
$ echo 'int main(){  return pthread_self(); }' | c gcc -include pthread.h -x c - -lpthread && ldd a.out | grep pthread
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x0000003000c00000)
$ echo 'int main(){ return 0; }' | c gcc -include pthread.h -x c - -pthread && ldd a.out | grep pthread
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x0000003000c00000) 
like image 610
PSkocik Avatar asked Dec 21 '16 16:12

PSkocik


People also ask

What is a dynamically statically linked file?

Statically-linked files are 'locked' to the executable at link time so they never change. A dynamically linked file referenced by an executable can change just by replacing the file on the disk. This allows updates to functionality without having to re-link the code; the loader re-links every time you run it.

Which is better static or dynamic library?

In C exist two kinds of libraries the first ones are the static that allows us to link to the program and are not relevant during the runtime, and the other ones are called dynamic libraries those are preferable use when you run a lot of programs at the same time who are using the same library and you want to be more ...

What is static linking and dynamic linking?

Definition. Static linking is the process of copying all library modules used in the program into the final executable image. In contrast, dynamic linking is the process of loading the external shared libraries into the program and then binds those shared libraries dynamically to the program.

What are static and dynamic libraries?

Static libraries, unlike dynamics, gather object files into one, while dynamics exist as separate files outside the executable, which means that static libraries add those files as they link, before it becomes an executable binary and dynamic libraries also have object files but are not added during compilation, they ...


2 Answers

The idea that you should use GCC's special option -pthread instead of -lpthread is outdated by probably some decade and a half (with respect to glibc, that is). In modern glibc, the switch to threading is entirely dynamic, based on whether the pthreads library is linked or not. Nothing in the glibc headers changes its behavior based on whether _REENTRANT is defined.

As an example of the dynamic switching, consider FILE * streams. Certain operations on streams are locking, like putc. Whether you're compiling a single-threaded program or not, it calls the same putc function; it is not re-routed by the preprocessor to a "pthread-aware" putc. What happens is that do-nothing stub functions are used to go through the motions of locking and unlocking. These functions get overridden to real ones when the threading library is linked in.



I just did a cursory grep through the include file tree of a glibc installation. In features.h, _REENTRANT causes __USE_REENTRANT to be defined. In turn, exactly one thing seems to depend on whether __USE_REENTRANT is present, but has a parallel condition which also enables it. Namely, in <unistd.h> there is this:

#if defined __USE_REENTRANT || defined __USE_POSIX199506
/* Return at most NAME_LEN characters of the login name of the user in NAME.
   If it cannot be determined or some other error occurred, return the error
   code.  Otherwise return 0.

   This function is a possible cancellation point and therefore not
   marked with __THROW.  */
extern int getlogin_r (char *__name, size_t __name_len) __nonnull ((1));
#endif

This looks dubious and is obsolete; I can't find it in the master branch of the glibc git repo.

And, oh look, just mere days ago (December 6) a commit was made on this topic:

https://sourceware.org/git/?p=glibc.git;a=commit;h=c03073774f915fe7841c2b551fe304544143470f

Make _REENTRANT and _THREAD_SAFE aliases for _POSIX_C_SOURCE=199506L.

For many years, the only effect of these macros has been to make
unistd.h declare getlogin_r.  _POSIX_C_SOURCE >= 199506L also causes
this function to be declared.  However, people who don't carefully
read all the headers might be confused into thinking they need to
define _REENTRANT for any threaded code (as was indeed the case a long
time ago).

Among the changes:

--- a/posix/unistd.h
+++ b/posix/unistd.h
@@ -849,7 +849,7 @@ extern int tcsetpgrp (int __fd, __pid_t __pgrp_id) __THROW;
    This function is a possible cancellation point and therefore not
    marked with __THROW.  */
 extern char *getlogin (void);
-#if defined __USE_REENTRANT || defined __USE_POSIX199506
+#ifdef __USE_POSIX199506
 /* Return at most NAME_LEN characters of the login name of the user in NAME.
    If it cannot be determined or some other error occurred, return the error
    code.  Otherwise return 0.

See? :)

like image 130
Kaz Avatar answered Sep 20 '22 15:09

Kaz


The other answer explains that -pthread (at both compile and link time) is functionally equivalent to -lpthread (at link time only) when the C library is the GNU C library. But that's not the only C library in the world.

I do not know whether any of the current generation of POSIX-compliant operating systems require anything more than -lpthread at link time for a threaded application, but if you use -pthread at both compile and link time, you will at least make life easier for people trying to keep old iron running.

Having said that, old iron will also be happier if you don't use -pthread (or -lpthread) on programs that don't need to use threads. "Generic project builds" are not a good idea.

The problem of shared libraries getting pulled in when they don't need to be is best solved by -Wl,--as-needed (with GNU-compatible linkers). This is only not on by default for backward compatibility's sake.

like image 32
zwol Avatar answered Sep 19 '22 15:09

zwol