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? :)