Thread: thread_test.c problems
[Sorry, I hit the wrong butt on and sent this earlier before I meant to] When I try to run thread_test.c from the CVS tip, it hangs in an infinite CPU loop on both linux (RedHat AS 3.0, gcc 3.2.3) and Mac OS X 10.3.3 (gcc 3.3). I've also tried down to gcc 2.96 on Mac OS X. If I compile it with -g instead of -O2 on linux, it runs to completion and gives me: Add this to your template/$port file: STRERROR_THREADSAFE=yes GETPWUID_THREADSAFE=no GETHOSTBYNAME_THREADSAFE=no On Mac OS X, it gives me: Add this to your template/$port file: STRERROR_THREADSAFE=yes GETPWUID_THREADSAFE=yes GETHOSTBYNAME_THREADSAFE=yes If I modify the two while loops while (errno2_set == 0) while (errno1_set == 0) To execute a 'print' statement or a 'time(NULL)' instead of a null loop, then it runs to completion with -O2. If I run the 7.4.2 released version of thread_test.c, for both platforms I get: Add this to your template/$port file: NEED_REENTRANT_FUNCS=yes There seems to be two problems 1. It would appear the compiler is optimizing the while loop to be an infinite loop. Other explanations? 2. The answers both can't be right... On OS X, the 7.4.2 version says NEED_REENTRANT_FUNCS=yes, but with the tip version it says all are thread safe. On linux, the make run (putting 'time(NULL)' in the loop): make gcc -O2 -fno-strict-aliasing -Wall -Wmissing-prototypes -Wmissing-declarations -D_REENTRANT -D_THREAD_SAFE -D_POSIX_PTHREAD_SEMANTICS -I../../../src/include -D_GNU_SOURCE -c -o thread_test.o thread_test.c -MMD gcc -O2 -fno-strict-aliasing -Wall -Wmissing-prototypes -Wmissing-declarations -D_REENTRANT -D_THREAD_SAFE -D_POSIX_PTHREAD_SEMANTICS -L../../../src/port -Wl,-rpath,/wdisk/wrp/opensrc/as30/local/pgsql7.4.2/lib -lpthread thread_test.o -lz -lcrypt -lresolv -lnsl -ldl -lm -lbsd -lpgport -o thread_test [wrp@juniper thread]$ !. ./thread_test Make sure you have added any needed 'THREAD_CPPFLAGS' and 'THREAD_LIBS' defines to your template/$port file before compiling this program. Add this to your template/$port file: STRERROR_THREADSAFE=yes GETPWUID_THREADSAFE=no GETHOSTBYNAME_THREADSAFE=no
wespvp, have you tried adding a volatile keyword to the int volatile errno1_set = 0; int volatile errno2_set = 0; that should stop while-loop optimizing for cases where the variable is modified in a scope the compiler would be ignorantof, and precludes compiler while-loop optimization. That would then tell you if it was a while loop optimizationproblem. As for me on RH 8.0 gcc -v Reading specs from /usr/lib/gcc-lib/i386-redhat-linux/3.2/specs Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix--disable-checking --host=i386-redhat-linux --with-system-zlib --enable-__cxa_atexit Thread model: posix gcc version 3.2 20020903 (Red Hat Linux 8.0 3.2-7) sorry, they all run yes/no/no On Sat, Apr 03, 2004 at 03:40:01PM -0600, wespvp@syntegra.com wrote: > [Sorry, I hit the wrong butt on and sent this earlier before I meant to] > > When I try to run thread_test.c from the CVS tip, it hangs in an infinite > CPU loop on both linux (RedHat AS 3.0, gcc 3.2.3) and Mac OS X 10.3.3 (gcc > 3.3). I've also tried down to gcc 2.96 on Mac OS X. > > If I compile it with -g instead of -O2 on linux, it runs to completion and > gives me: > > Add this to your template/$port file: > > STRERROR_THREADSAFE=yes > GETPWUID_THREADSAFE=no > GETHOSTBYNAME_THREADSAFE=no > > On Mac OS X, it gives me: > > Add this to your template/$port file: > > STRERROR_THREADSAFE=yes > GETPWUID_THREADSAFE=yes > GETHOSTBYNAME_THREADSAFE=yes > > If I modify the two while loops > > while (errno2_set == 0) > > while (errno1_set == 0) > > To execute a 'print' statement or a 'time(NULL)' instead of a null loop, > then it runs to completion with -O2. > > > > If I run the 7.4.2 released version of thread_test.c, for both platforms I > get: > > Add this to your template/$port file: > > NEED_REENTRANT_FUNCS=yes > > There seems to be two problems > > 1. It would appear the compiler is optimizing the while loop to be an > infinite loop. Other explanations? > > 2. The answers both can't be right... On OS X, the 7.4.2 version says > NEED_REENTRANT_FUNCS=yes, but with the tip version it says all are thread > safe. > > > > On linux, the make run (putting 'time(NULL)' in the loop): > > make > gcc -O2 -fno-strict-aliasing -Wall -Wmissing-prototypes > -Wmissing-declarations -D_REENTRANT -D_THREAD_SAFE > -D_POSIX_PTHREAD_SEMANTICS -I../../../src/include -D_GNU_SOURCE -c -o > thread_test.o thread_test.c -MMD > gcc -O2 -fno-strict-aliasing -Wall -Wmissing-prototypes > -Wmissing-declarations -D_REENTRANT -D_THREAD_SAFE > -D_POSIX_PTHREAD_SEMANTICS -L../../../src/port > -Wl,-rpath,/wdisk/wrp/opensrc/as30/local/pgsql7.4.2/lib -lpthread > thread_test.o -lz -lcrypt -lresolv -lnsl -ldl -lm -lbsd -lpgport -o > thread_test > [wrp@juniper thread]$ !. > ./thread_test > Make sure you have added any needed 'THREAD_CPPFLAGS' and 'THREAD_LIBS' > defines to your template/$port file before compiling this program. > > Add this to your template/$port file: > > STRERROR_THREADSAFE=yes > GETPWUID_THREADSAFE=no > GETHOSTBYNAME_THREADSAFE=no > > > > > ---------------------------(end of broadcast)--------------------------- > TIP 2: you can get off all lists at once with the unregister command > (send "unregister YourEmailAddressHere" to majordomo@postgresql.org) -- joe speigle www.sirfsup.com
On 4/4/04 12:33 AM, "joseph speigle" <joe.speigle@jklh.us> wrote: > have you tried adding a volatile keyword to the > > int volatile errno1_set = 0; > int volatile errno2_set = 0; > > that should stop while-loop optimizing for cases where the variable is > modified in a scope the compiler would be ignorant of, and precludes compiler > while-loop optimization. That would then tell you if it was a while loop > optimization problem. That cures the problem on all systems. What needs to be done to get this updated in the tip? > As for me on RH 8.0 > > gcc -v > Reading specs from /usr/lib/gcc-lib/i386-redhat-linux/3.2/specs > Configured with: ../configure --prefix=/usr --mandir=/usr/share/man > --infodir=/usr/share/info --enable-shared --enable-threads=posix > --disable-checking --host=i386-redhat-linux --with-system-zlib > --enable-__cxa_atexit > Thread model: posix > gcc version 3.2 20020903 (Red Hat Linux 8.0 3.2-7) > > sorry, they all run yes/no/no I don't know what is different, but I've tried it on RH 7.2, RH AS 3.0, and Mac OS X. All hang in an infinite loop with the tip version of thread_test.c, and all work if I add 'volatile' to the definitions of errno1_set and errno2_set. There's still the question of which version of the program is giving the right answers - the 7.4.2 version or the tip version? RH 7.2: [wrp@cherry thread]$ gcc -v Reading specs from /usr/lib/gcc-lib/i386-redhat-linux/2.96/specs gcc version 2.96 20000731 (Red Hat Linux 7.2 2.96-112.7.2) RH AS 3.0: $ gcc -v Reading specs from /usr/lib/gcc-lib/i386-redhat-linux/3.2.3/specs Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --disable-checking --with-system-zlib --enable-__cxa_atexit --host=i386-redhat-linux Thread model: posix gcc version 3.2.3 20030502 (Red Hat Linux 3.2.3-24) Mac OS X: % gcc -v Reading specs from /usr/libexec/gcc/darwin/ppc/3.3/specs Thread model: posix gcc version 3.3 20030304 (Apple Computer, Inc. build 1495) Wes
wespvp@syntegra.com wrote: > On 4/4/04 12:33 AM, "joseph speigle" <joe.speigle@jklh.us> wrote: > > > have you tried adding a volatile keyword to the > > > > int volatile errno1_set = 0; > > int volatile errno2_set = 0; > > > > that should stop while-loop optimizing for cases where the variable is > > modified in a scope the compiler would be ignorant of, and precludes compiler > > while-loop optimization. That would then tell you if it was a while loop > > optimization problem. > > That cures the problem on all systems. What needs to be done to get this > updated in the tip? > > > As for me on RH 8.0 > > > > gcc -v > > Reading specs from /usr/lib/gcc-lib/i386-redhat-linux/3.2/specs > > Configured with: ../configure --prefix=/usr --mandir=/usr/share/man > > --infodir=/usr/share/info --enable-shared --enable-threads=posix > > --disable-checking --host=i386-redhat-linux --with-system-zlib > > --enable-__cxa_atexit > > Thread model: posix > > gcc version 3.2 20020903 (Red Hat Linux 8.0 3.2-7) > > > > sorry, they all run yes/no/no > > I don't know what is different, but I've tried it on RH 7.2, RH AS 3.0, and > Mac OS X. All hang in an infinite loop with the tip version of > thread_test.c, and all work if I add 'volatile' to the definitions of > errno1_set and errno2_set. > > There's still the question of which version of the program is giving the > right answers - the 7.4.2 version or the tip version? I have applied the following patch to CVS head which does a getpid() in the loop, rather than nothing. getpid() should force a system call, which will make it more likely for the other thread to get CPU time and complete its tests. -- Bruce Momjian | http://candle.pha.pa.us pgman@candle.pha.pa.us | (610) 359-1001 + If your life is a hard drive, | 13 Roberts Road + Christ can be your backup. | Newtown Square, Pennsylvania 19073 Index: thread_test.c =================================================================== RCS file: /cvsroot/pgsql-server/src/tools/thread/thread_test.c,v retrieving revision 1.9 retrieving revision 1.10 diff -c -c -r1.9 -r1.10 *** thread_test.c 28 Mar 2004 02:37:31 -0000 1.9 --- thread_test.c 4 Apr 2004 17:23:54 -0000 1.10 *************** *** 105,111 **** /* wait for other thread to set errno */ errno1_set = 1; while (errno2_set == 0) ! /* loop */; if (errno != EEXIST) { fprintf(stderr, "errno not thread-safe; exiting\n"); --- 105,111 ---- /* wait for other thread to set errno */ errno1_set = 1; while (errno2_set == 0) ! getpid(); /* force system call */ if (errno != EEXIST) { fprintf(stderr, "errno not thread-safe; exiting\n"); *************** *** 128,135 **** passwd_p1 = NULL; /* force thread-safe failure report */ } ! hostent_p1 = gethostbyname("yahoo.com"); ! p = gethostbyname("slashdot.org"); if (hostent_p1 != p) { printf("Your gethostbyname() changes the static memory area between calls\n"); --- 128,135 ---- passwd_p1 = NULL; /* force thread-safe failure report */ } ! hostent_p1 = gethostbyname("www.yahoo.com"); ! p = gethostbyname("www.weather.com"); if (hostent_p1 != p) { printf("Your gethostbyname() changes the static memory area between calls\n"); *************** *** 151,157 **** /* wait for other thread to set errno */ errno2_set = 1; while (errno1_set == 0) ! /* loop */; if (errno != ENOENT) { fprintf(stderr, "errno not thread-safe; exiting\n"); --- 151,157 ---- /* wait for other thread to set errno */ errno2_set = 1; while (errno1_set == 0) ! getpid(); /* force system call */ if (errno != ENOENT) { fprintf(stderr, "errno not thread-safe; exiting\n"); *************** *** 174,181 **** passwd_p2 = NULL; /* force thread-safe failure report */ } ! hostent_p2 = gethostbyname("google.com"); ! p = gethostbyname("postgresql.org"); if (hostent_p2 != p) { printf("Your gethostbyname() changes the static memory area between calls\n"); --- 174,181 ---- passwd_p2 = NULL; /* force thread-safe failure report */ } ! hostent_p2 = gethostbyname("www.google.com"); ! p = gethostbyname("www.postgresql.org"); if (hostent_p2 != p) { printf("Your gethostbyname() changes the static memory area between calls\n");
> I have applied the following patch to CVS head which does a getpid() in > the loop, rather than nothing. getpid() should force a system call, > which will make it more likely for the other thread to get CPU time and > complete its tests. Works for me... However, there seems to be a reliability problem with the results: [g4:src/tools/thread] wp% ./thread_test Make sure you have added any needed 'THREAD_CPPFLAGS' and 'THREAD_LIBS' defines to your template/$port file before compiling this program. Add this to your template/$port file: STRERROR_THREADSAFE=yes GETPWUID_THREADSAFE=yes GETHOSTBYNAME_THREADSAFE=no [g4:src/tools/thread] wp% ./thread_test Make sure you have added any needed 'THREAD_CPPFLAGS' and 'THREAD_LIBS' defines to your template/$port file before compiling this program. Add this to your template/$port file: STRERROR_THREADSAFE=yes GETPWUID_THREADSAFE=yes GETHOSTBYNAME_THREADSAFE=yes It returns mostly 'yes' for all three, but sometimes returns 'no' for the last one. I get the same conflicting results whether I run with one or two CPU's enabled. Similarly, the 7.4.2 release is showing: % ./thread_test Make sure you have added any needed 'THREAD_CPPFLAGS' and 'THREAD_LIBS' defines to your template/$port file before compiling this program. All your non-*_r functions are thread-safe. Add this to your template/$port file: NEED_REENTRANT_FUNCS=no % ./thread_test Make sure you have added any needed 'THREAD_CPPFLAGS' and 'THREAD_LIBS' defines to your template/$port file before compiling this program. Your gethostbyname() is _not_ thread-safe Not all non-*_r functions are thread-safe. Add this to your template/$port file: NEED_REENTRANT_FUNCS=yes I assume the safe bet is GETHOSTBYNAME_THREADSAFE=no for the tip and NEED_REENTRANT_FUNCS=yes for 7.4.2? Can I rely on the other two being 'yes', or should they be set to 'no' also? Based on the linux template and the output of thread_test, I have set up the darwin template and compiled the CVS tip code on Mac OS X 10.3.3 with: # Apple's cpp-precomp seems a tad broken, so don't use it # (Note: on OS X before 10.2, you might need -traditional-cpp instead) #CC="$CC -no-cpp-precomp" # Select appropriate semaphore support USE_NAMED_POSIX_SEMAPHORES=1 # tools/thread/thread_test must be run THREAD_SUPPORT=yes THREAD_CPPFLAGS="-D_REENTRANT -D_THREAD_SAFE -D_POSIX_PTHREAD_SEMANTICS" THREAD_LIBS="-lpthread" STRERROR_THREADSAFE=yes GETPWUID_THREADSAFE=yes GETHOSTBYNAME_THREADSAFE=no #NEED_REENTRANT_FUNCS=yes I commented out the 'CC="$CC -no-cpp-precomp"' line and did not get any compile errors. Mac OS X 10.3.3 uses GCC 3.3. I know something changed between Mac OS X 10.2 and 10.3 regarding precomp (they also upgraded from gcc 2.96 to 3.3). It seems to compile ok on 10.3 regardless of the setting of this parameter, so unless it is important to have it enabled when possible, it is probably best to leave it off for backwards compatibility? I also added all of the thread lines starting with the comment '# tools/thread/thread_test must be run' based on the output of thread_test. The released PostgreSQL 7.4.2 says I should use 'NEED_REENTRANT_FUNCS=yes'. Wes
wespvp@syntegra.com wrote: > Add this to your template/$port file: > > STRERROR_THREADSAFE=yes > GETPWUID_THREADSAFE=yes > GETHOSTBYNAME_THREADSAFE=no > > [g4:src/tools/thread] wp% ./thread_test > Make sure you have added any needed 'THREAD_CPPFLAGS' and 'THREAD_LIBS' > defines to your template/$port file before compiling this program. > > Add this to your template/$port file: > > STRERROR_THREADSAFE=yes > GETPWUID_THREADSAFE=yes > GETHOSTBYNAME_THREADSAFE=yes > > > It returns mostly 'yes' for all three, but sometimes returns 'no' for the > last one. I get the same conflicting results whether I run with one or two > CPU's enabled. > OK, I know the cause of this. The problem is that sometimes hostnames don't resolve, and the bigger problem is that it requires an internet connection to run the tests. The attached patch tests for 'localhost' and your local hostname, so it should work reliably. > Similarly, the 7.4.2 release is showing: > > % ./thread_test > Make sure you have added any needed 'THREAD_CPPFLAGS' and 'THREAD_LIBS' > defines to your template/$port file before compiling this program. > > All your non-*_r functions are thread-safe. > Add this to your template/$port file: > > NEED_REENTRANT_FUNCS=no > > > % ./thread_test > Make sure you have added any needed 'THREAD_CPPFLAGS' and 'THREAD_LIBS' > defines to your template/$port file before compiling this program. > > Your gethostbyname() is _not_ thread-safe > Not all non-*_r functions are thread-safe. > Add this to your template/$port file: > > NEED_REENTRANT_FUNCS=yes > > > > I assume the safe bet is GETHOSTBYNAME_THREADSAFE=no for the tip and > NEED_REENTRANT_FUNCS=yes for 7.4.2? Can I rely on the other two being > 'yes', or should they be set to 'no' also? Yes, that is the safe bet on 7.4.X. 7.5 will use individual entries for each function, and in fact we might have this all merged into configure by then anyway. > > Based on the linux template and the output of thread_test, I have set up the > darwin template and compiled the CVS tip code on Mac OS X 10.3.3 with: > > > > # Apple's cpp-precomp seems a tad broken, so don't use it > # (Note: on OS X before 10.2, you might need -traditional-cpp instead) > #CC="$CC -no-cpp-precomp" > > # Select appropriate semaphore support > USE_NAMED_POSIX_SEMAPHORES=1 > > # tools/thread/thread_test must be run > THREAD_SUPPORT=yes > THREAD_CPPFLAGS="-D_REENTRANT -D_THREAD_SAFE -D_POSIX_PTHREAD_SEMANTICS" > THREAD_LIBS="-lpthread" > > STRERROR_THREADSAFE=yes > GETPWUID_THREADSAFE=yes > GETHOSTBYNAME_THREADSAFE=no > > #NEED_REENTRANT_FUNCS=yes > > > > > I commented out the 'CC="$CC -no-cpp-precomp"' line and did not get any > compile errors. Mac OS X 10.3.3 uses GCC 3.3. I know something changed > between Mac OS X 10.2 and 10.3 regarding precomp (they also upgraded from > gcc 2.96 to 3.3). It seems to compile ok on 10.3 regardless of the setting > of this parameter, so unless it is important to have it enabled when > possible, it is probably best to leave it off for backwards compatibility? > > I also added all of the thread lines starting with the comment '# > tools/thread/thread_test must be run' based on the output of thread_test. > The released PostgreSQL 7.4.2 says I should use 'NEED_REENTRANT_FUNCS=yes'. Yes, in 7.4.X, you only need that single entry. Thanks for the testing. -- Bruce Momjian | http://candle.pha.pa.us pgman@candle.pha.pa.us | (610) 359-1001 + If your life is a hard drive, | 13 Roberts Road + Christ can be your backup. | Newtown Square, Pennsylvania 19073 Index: src/tools/thread/thread_test.c =================================================================== RCS file: /cvsroot/pgsql-server/src/tools/thread/thread_test.c,v retrieving revision 1.10 diff -c -c -r1.10 thread_test.c *** src/tools/thread/thread_test.c 4 Apr 2004 17:23:54 -0000 1.10 --- src/tools/thread/thread_test.c 5 Apr 2004 01:22:04 -0000 *************** *** 35,40 **** --- 35,42 ---- void func_call_1(void); void func_call_2(void); + char myhostname[MAXHOSTNAMELEN]; + int errno1_set = 0; int errno2_set = 0; *************** *** 61,66 **** --- 63,74 ---- return 1; } + if (gethostname(myhostname, MAXHOSTNAMELEN) != 0) + { + fprintf(stderr, "can not get local hostname, exiting\n"); + exit(1); + } + printf("\ Make sure you have added any needed 'THREAD_CPPFLAGS' and 'THREAD_LIBS'\n\ defines to your template/$port file before compiling this program.\n\n" *************** *** 128,135 **** passwd_p1 = NULL; /* force thread-safe failure report */ } ! hostent_p1 = gethostbyname("www.yahoo.com"); ! p = gethostbyname("www.weather.com"); if (hostent_p1 != p) { printf("Your gethostbyname() changes the static memory area between calls\n"); --- 136,144 ---- passwd_p1 = NULL; /* force thread-safe failure report */ } ! /* threads do this in opposite order */ ! hostent_p1 = gethostbyname(myhostname); ! p = gethostbyname("localhost"); if (hostent_p1 != p) { printf("Your gethostbyname() changes the static memory area between calls\n"); *************** *** 174,181 **** passwd_p2 = NULL; /* force thread-safe failure report */ } ! hostent_p2 = gethostbyname("www.google.com"); ! p = gethostbyname("www.postgresql.org"); if (hostent_p2 != p) { printf("Your gethostbyname() changes the static memory area between calls\n"); --- 183,191 ---- passwd_p2 = NULL; /* force thread-safe failure report */ } ! /* threads do this in opposite order */ ! hostent_p2 = gethostbyname("localhost"); ! p = gethostbyname(myhostname); if (hostent_p2 != p) { printf("Your gethostbyname() changes the static memory area between calls\n");
Bruce Momjian <pgman@candle.pha.pa.us> writes: > wespvp@syntegra.com wrote: > have you tried adding a volatile keyword to the > int volatile errno1_set = 0; > int volatile errno2_set = 0; > > I have applied the following patch to CVS head which does a getpid() in > the loop, rather than nothing. That does not cure the bug identified by wespvp. It may make it a little less likely that the compiler will choose to optimize out the loop test, but only adding "volatile" really fixes the problem in a language-standard-compliant way. regards, tom lane
Tom Lane wrote: > Bruce Momjian <pgman@candle.pha.pa.us> writes: > > wespvp@syntegra.com wrote: > > have you tried adding a volatile keyword to the > > int volatile errno1_set = 0; > > int volatile errno2_set = 0; > > > > I have applied the following patch to CVS head which does a getpid() in > > the loop, rather than nothing. > > That does not cure the bug identified by wespvp. It may make it a > little less likely that the compiler will choose to optimize out the > loop test, but only adding "volatile" really fixes the problem in > a language-standard-compliant way. Thanks, 'volatile' added to the thread-specific errno variables: volatile int errno1_set = 0; volatile int errno2_set = 0; -- Bruce Momjian | http://candle.pha.pa.us pgman@candle.pha.pa.us | (610) 359-1001 + If your life is a hard drive, | 13 Roberts Road + Christ can be your backup. | Newtown Square, Pennsylvania 19073
On 4/4/04 7:28 PM, "Bruce Momjian" <pgman@candle.pha.pa.us> wrote: > OK, I know the cause of this. The problem is that sometimes hostnames > don't resolve, and the bigger problem is that it requires an internet > connection to run the tests. The attached patch tests for 'localhost' > and your local hostname, so it should work reliably. I did a cvs update, make, then rebuilt and tested thread_test. I ran it about 120 times and got "GETHOSTBYNAME_THREADSAFE=yes" almost all of the time. I got "GETHOSTBYNAME_THREADSAFE=no" three times. The other two were always "yes". I did verify that both the "volatile" and "localhost" changes were in there. Dumb question... Why would you not always use the _r functions if they exist? Wes
wespvp@syntegra.com wrote: > On 4/4/04 7:28 PM, "Bruce Momjian" <pgman@candle.pha.pa.us> wrote: > > > OK, I know the cause of this. The problem is that sometimes hostnames > > don't resolve, and the bigger problem is that it requires an internet > > connection to run the tests. The attached patch tests for 'localhost' > > and your local hostname, so it should work reliably. > > I did a cvs update, make, then rebuilt and tested thread_test. I ran it > about 120 times and got "GETHOSTBYNAME_THREADSAFE=yes" almost all of the > time. I got "GETHOSTBYNAME_THREADSAFE=no" three times. The other two were > always "yes". Yep, I can reproduce this on BSD/OS too, so it must be something wrong with my program. I see: $ for X in `jot 1000`; do thread_test |grep -10 '=no' && echo $X; done|less Make sure you have added any needed 'THREAD_CPPFLAGS' and 'THREAD_LIBS' defines to your template/$port file before compiling this program. Add this to your template/$port file: STRERROR_THREADSAFE=yes GETPWUID_THREADSAFE=no GETHOSTBYNAME_THREADSAFE=no 919 I bet the problem is that I am accessing thread-specific pointers after the thread exits. It is possible thread 1 completes before thread2 gets to the getpwuid and gethostbyname tests, and then reuses the thread-specific pointer. Let me work on a patch and email it to you in a few minutes. > I did verify that both the "volatile" and "localhost" changes were in there. > > Dumb question... Why would you not always use the _r functions if they > exist? Yes, we do use *_r functions in 7.5 if they exist, but in 7.4.X, I think we use the non-R if we can, though we actually just use getaddrinfo() in 7.4.X if it exists. Basically, the threading tests are still in flux, as you can see, in 7.4.X. It works, but it isn't 100% configure perfect yet. -- Bruce Momjian | http://candle.pha.pa.us pgman@candle.pha.pa.us | (610) 359-1001 + If your life is a hard drive, | 13 Roberts Road + Christ can be your backup. | Newtown Square, Pennsylvania 19073
Bruce Momjian wrote: > > I did a cvs update, make, then rebuilt and tested thread_test. I ran it > > about 120 times and got "GETHOSTBYNAME_THREADSAFE=yes" almost all of the > > time. I got "GETHOSTBYNAME_THREADSAFE=no" three times. The other two were > > always "yes". > > Yep, I can reproduce this on BSD/OS too, so it must be something wrong > with my program. I see: > > $ for X in `jot 1000`; do thread_test |grep -10 '=no' && echo $X; > done|less > Make sure you have added any needed 'THREAD_CPPFLAGS' and 'THREAD_LIBS' > defines to your template/$port file before compiling this program. > > Add this to your template/$port file: > > STRERROR_THREADSAFE=yes > GETPWUID_THREADSAFE=no > GETHOSTBYNAME_THREADSAFE=no > 919 > > I bet the problem is that I am accessing thread-specific pointers after > the thread exits. It is possible thread 1 completes before thread2 gets > to the getpwuid and gethostbyname tests, and then reuses the > thread-specific pointer. Let me work on a patch and email it to you in > a few minutes. OK, new patch applied that causes all threads to wait until the parent checks their thread-specific pointers. I ran 1000 tests and all passed. Hopefully it will good for you too. -- Bruce Momjian | http://candle.pha.pa.us pgman@candle.pha.pa.us | (610) 359-1001 + If your life is a hard drive, | 13 Roberts Road + Christ can be your backup. | Newtown Square, Pennsylvania 19073 Index: src/tools/thread/thread_test.c =================================================================== RCS file: /cvsroot/pgsql-server/src/tools/thread/thread_test.c,v retrieving revision 1.12 diff -c -c -r1.12 thread_test.c *** src/tools/thread/thread_test.c 5 Apr 2004 02:22:14 -0000 1.12 --- src/tools/thread/thread_test.c 5 Apr 2004 05:40:13 -0000 *************** *** 40,45 **** --- 40,48 ---- volatile int errno1_set = 0; volatile int errno2_set = 0; + volatile int thread1_done = 0; + volatile int thread2_done = 0; + char *strerror_p1; char *strerror_p2; *************** *** 49,57 **** struct hostent *hostent_p1; struct hostent *hostent_p2; ! pthread_mutex_t singlethread_lock1 = PTHREAD_MUTEX_INITIALIZER; ! pthread_mutex_t singlethread_lock2 = PTHREAD_MUTEX_INITIALIZER; ! int main(int argc, char *argv[]) { pthread_t thread1, --- 52,59 ---- struct hostent *hostent_p1; struct hostent *hostent_p2; ! pthread_mutex_t init_mutex = PTHREAD_MUTEX_INITIALIZER; ! int main(int argc, char *argv[]) { pthread_t thread1, *************** *** 73,82 **** Make sure you have added any needed 'THREAD_CPPFLAGS' and 'THREAD_LIBS'\n\ defines to your template/$port file before compiling this program.\n\n" ); pthread_create(&thread1, NULL, (void * (*)(void *)) func_call_1, NULL); pthread_create(&thread2, NULL, (void * (*)(void *)) func_call_2, NULL); ! pthread_join(thread1, NULL); ! pthread_join(thread2, NULL); printf("Add this to your template/$port file:\n\n"); --- 75,89 ---- Make sure you have added any needed 'THREAD_CPPFLAGS' and 'THREAD_LIBS'\n\ defines to your template/$port file before compiling this program.\n\n" ); + + /* Hold lock until we are ready for the child threads to exit. */ + pthread_mutex_lock(&init_mutex); + pthread_create(&thread1, NULL, (void * (*)(void *)) func_call_1, NULL); pthread_create(&thread2, NULL, (void * (*)(void *)) func_call_2, NULL); ! ! while (thread1_done == 0 || thread2_done == 0) ! getpid(); /* force system call */ printf("Add this to your template/$port file:\n\n"); *************** *** 94,100 **** --- 101,112 ---- printf("GETHOSTBYNAME_THREADSAFE=yes\n"); else printf("GETHOSTBYNAME_THREADSAFE=no\n"); + + pthread_mutex_unlock(&init_mutex); /* let children exit */ + pthread_join(thread1, NULL); /* clean up children */ + pthread_join(thread2, NULL); + return 0; } *************** *** 110,116 **** fprintf(stderr, "could not generate failure for create file in /tmp, exiting\n"); exit(1); } ! /* wait for other thread to set errno */ errno1_set = 1; while (errno2_set == 0) getpid(); /* force system call */ --- 122,132 ---- fprintf(stderr, "could not generate failure for create file in /tmp, exiting\n"); exit(1); } ! /* ! * Wait for other thread to set errno. ! * We can't use thread-specific locking here because it might ! * affect errno. ! */ errno1_set = 1; while (errno2_set == 0) getpid(); /* force system call */ *************** *** 144,149 **** --- 160,169 ---- printf("Your gethostbyname() changes the static memory area between calls\n"); hostent_p1 = NULL; /* force thread-safe failure report */ } + + thread1_done = 1; + pthread_mutex_lock(&init_mutex); /* wait for parent to test */ + pthread_mutex_unlock(&init_mutex); } *************** *** 157,163 **** fprintf(stderr, "Read-only open succeeded without create, exiting\n"); exit(1); } ! /* wait for other thread to set errno */ errno2_set = 1; while (errno1_set == 0) getpid(); /* force system call */ --- 177,187 ---- fprintf(stderr, "Read-only open succeeded without create, exiting\n"); exit(1); } ! /* ! * Wait for other thread to set errno. ! * We can't use thread-specific locking here because it might ! * affect errno. ! */ errno2_set = 1; while (errno1_set == 0) getpid(); /* force system call */ *************** *** 191,194 **** --- 215,222 ---- printf("Your gethostbyname() changes the static memory area between calls\n"); hostent_p2 = NULL; /* force thread-safe failure report */ } + + thread2_done = 1; + pthread_mutex_lock(&init_mutex); /* wait for parent to test */ + pthread_mutex_unlock(&init_mutex); }
On 4/4/04 11:43 PM, "Bruce Momjian" <pgman@candle.pha.pa.us> wrote: > OK, new patch applied that causes all threads to wait until the parent > checks their thread-specific pointers. I ran 1000 tests and all passed. > Hopefully it will good for you too. I'll try to give it a test tonight. >> Dumb question... Why would you not always use the _r functions if they >> exist? > > Yes, we do use *_r functions in 7.5 if they exist, but in 7.4.X, I think > we use the non-R if we can, though we actually just use getaddrinfo() in > 7.4.X if it exists. Basically, the threading tests are still in flux, > as you can see, in 7.4.X. It works, but it isn't 100% configure perfect > yet. I'm still not clear on this... The thread_test program checks to see if the non-r functions are thread safe. If so, it directs you to set xxxx=yes in the template file - I assume that causes the non-r function to be used. If they are not thread safe, it directs you to use xxxx=no - which I assume causes the *_r functions to be used. Why would you not *always* use the _r functions if they exist, and only check for thread safety if the _r functions do not exist? Or, am I misunderstanding how the xxx=yes is used? Wes
wespvp@syntegra.com wrote: > On 4/4/04 11:43 PM, "Bruce Momjian" <pgman@candle.pha.pa.us> wrote: > > > OK, new patch applied that causes all threads to wait until the parent > > checks their thread-specific pointers. I ran 1000 tests and all passed. > > Hopefully it will good for you too. > > I'll try to give it a test tonight. Please grab CVS. I added sched_yield() too. > > >> Dumb question... Why would you not always use the _r functions if they > >> exist? > > > > Yes, we do use *_r functions in 7.5 if they exist, but in 7.4.X, I think > > we use the non-R if we can, though we actually just use getaddrinfo() in > > 7.4.X if it exists. Basically, the threading tests are still in flux, > > as you can see, in 7.4.X. It works, but it isn't 100% configure perfect > > yet. > > I'm still not clear on this... The thread_test program checks to see if the > non-r functions are thread safe. If so, it directs you to set xxxx=yes in > the template file - I assume that causes the non-r function to be used. If > they are not thread safe, it directs you to use xxxx=no - which I assume > causes the *_r functions to be used. Why would you not *always* use the _r > functions if they exist, and only check for thread safety if the _r > functions do not exist? > > Or, am I misunderstanding how the xxx=yes is used? In 7.4.X, the thought was that if the native function are already thread-safe, why bother calling the *_r functions, but in 7.5, we decided it was better to use the *_r functions --- again, 7.4.X has threads working, but the configure issues were in flux as we learned how each platform handled threading. -- Bruce Momjian | http://candle.pha.pa.us pgman@candle.pha.pa.us | (610) 359-1001 + If your life is a hard drive, | 13 Roberts Road + Christ can be your backup. | Newtown Square, Pennsylvania 19073
Bruce Momjian <pgman@candle.pha.pa.us> writes: > wespvp@syntegra.com wrote: > > On 4/4/04 11:43 PM, "Bruce Momjian" <pgman@candle.pha.pa.us> wrote: > > > > > OK, new patch applied that causes all threads to wait until the parent > > > checks their thread-specific pointers. I ran 1000 tests and all passed. > > > Hopefully it will good for you too. > > > > I'll try to give it a test tonight. > > Please grab CVS. I added sched_yield() too. Make sure to test this on linux 2.6. They changed sched_yield() to not cause context switches in a lot of cases where it did previously. You might need a usleep() there instead or in addition. -- greg
Greg Stark wrote: > Bruce Momjian <pgman@candle.pha.pa.us> writes: > > > wespvp@syntegra.com wrote: > > > On 4/4/04 11:43 PM, "Bruce Momjian" <pgman@candle.pha.pa.us> wrote: > > > > > > > OK, new patch applied that causes all threads to wait until the parent > > > > checks their thread-specific pointers. I ran 1000 tests and all passed. > > > > Hopefully it will good for you too. > > > > > > I'll try to give it a test tonight. > > > > Please grab CVS. I added sched_yield() too. > > Make sure to test this on linux 2.6. They changed sched_yield() to not cause > context switches in a lot of cases where it did previously. You might need a > usleep() there instead or in addition. Usleep is probably more unportable than sched_yield on platforms that support threads. I actually don't need sched_yield to context switch, only to allow the other threads to complete. -- Bruce Momjian | http://candle.pha.pa.us pgman@candle.pha.pa.us | (610) 359-1001 + If your life is a hard drive, | 13 Roberts Road + Christ can be your backup. | Newtown Square, Pennsylvania 19073
On 4/5/04 8:31 AM, "Bruce Momjian" <pgman@candle.pha.pa.us> wrote: >>> OK, new patch applied that causes all threads to wait until the parent >>> checks their thread-specific pointers. I ran 1000 tests and all passed. >>> Hopefully it will good for you too. >> >> I'll try to give it a test tonight. > > Please grab CVS. I added sched_yield() too. Ok, I did a cvs update and reran the test. It now consistently returns 'YES' to all three questions. Thanks. What needs to be done to get the standard Darwin template file updated to enable threading? Wes
wespvp@syntegra.com wrote: > On 4/5/04 8:31 AM, "Bruce Momjian" <pgman@candle.pha.pa.us> wrote: > > >>> OK, new patch applied that causes all threads to wait until the parent > >>> checks their thread-specific pointers. I ran 1000 tests and all passed. > >>> Hopefully it will good for you too. > >> > >> I'll try to give it a test tonight. > > > > Please grab CVS. I added sched_yield() too. > > Ok, I did a cvs update and reran the test. It now consistently returns > 'YES' to all three questions. Thanks. > > What needs to be done to get the standard Darwin template file updated to > enable threading? Oh, that is a problem because other linux's show 'no' for the last two. My plan is to have 'configure' run this program as part of its operation, and Jan has some thread configure scripts, and this will all be automated in 7.5 so no one will have to run the program manually. -- Bruce Momjian | http://candle.pha.pa.us pgman@candle.pha.pa.us | (610) 359-1001 + If your life is a hard drive, | 13 Roberts Road + Christ can be your backup. | Newtown Square, Pennsylvania 19073
Bruce Momjian <pgman@candle.pha.pa.us> writes: > My plan is to have 'configure' run this program as part of its > operation, Peter's not going to be happy with you ;-) Runtime configure tests are not part of the Grand Plan --- ideally configure should only have to do compile and link tests. regards, tom lane
Tom Lane wrote: > Bruce Momjian <pgman@candle.pha.pa.us> writes: > > My plan is to have 'configure' run this program as part of its > > operation, > > Peter's not going to be happy with you ;-) Runtime configure tests are > not part of the Grand Plan --- ideally configure should only have to do > compile and link tests. Yep, I am sure he isn't, but looking at platforms that have different thread-safety capabilities, I can't see a way around it. We could argue that the thread test is testing the thread library, not the actual computer it is running in. For example, it isn't do a 'df'. -- Bruce Momjian | http://candle.pha.pa.us pgman@candle.pha.pa.us | (610) 359-1001 + If your life is a hard drive, | 13 Roberts Road + Christ can be your backup. | Newtown Square, Pennsylvania 19073
I have just commited to CVS code that will do all the compile/library flags and thread tests automatically. Let me know how it works for you. Thanks. --------------------------------------------------------------------------- wespvp@syntegra.com wrote: > On 4/5/04 8:31 AM, "Bruce Momjian" <pgman@candle.pha.pa.us> wrote: > > >>> OK, new patch applied that causes all threads to wait until the parent > >>> checks their thread-specific pointers. I ran 1000 tests and all passed. > >>> Hopefully it will good for you too. > >> > >> I'll try to give it a test tonight. > > > > Please grab CVS. I added sched_yield() too. > > Ok, I did a cvs update and reran the test. It now consistently returns > 'YES' to all three questions. Thanks. > > What needs to be done to get the standard Darwin template file updated to > enable threading? > > Wes > > > ---------------------------(end of broadcast)--------------------------- > TIP 7: don't forget to increase your free space map settings > -- Bruce Momjian | http://candle.pha.pa.us pgman@candle.pha.pa.us | (610) 359-1001 + If your life is a hard drive, | 13 Roberts Road + Christ can be your backup. | Newtown Square, Pennsylvania 19073
On 4/23/04 6:59 PM, "Bruce Momjian" <pgman@candle.pha.pa.us> wrote: > > I have just commited to CVS code that will do all the compile/library > flags and thread tests automatically. Let me know how it works for > you. Thanks. No, I don't think it is right. I did a 'cvs update', then ran 'configure'. Templates/darwin contains the information below. I don't know if it is supposed to contain the three *_TREADSAFE lines any more, but shouldn't it at least have the 'THREAD_SUPPORT' and 'THREAD_LIBS' entries? The output of thread_test run manually is: wrp% ./thread_test Your errno is thread-safe. Your system has sterror_r(); it does not need strerror(). Your system has getpwuid_r(); it does not need getpwuid(). Your system has getaddrinfo(); it does not need gethostbyname() or gethostbyname_r(). Your platform is thread-safe. ------ The current darwin file: ------ # Apple's cpp-precomp seems a tad broken, so don't use it # (Note: on OS X before 10.2, you might need -traditional-cpp instead) CC="$CC -no-cpp-precomp" # Select appropriate semaphore support USE_NAMED_POSIX_SEMAPHORES=1 # verified Mac OS X 10.3.3, Darwin Kernel Version 7.3.0, 2004-04-07 PTHREAD_CFLAGS="-D_REENTRANT -D_THREAD_SAFE -D_POSIX_PTHREAD_SEMANTICS" ------- The darwin file I had been using with 10.3.3 is: ------- # Apple's cpp-precomp seems a tad broken, so don't use it # (Note: on OS X before 10.2, you might need -traditional-cpp instead) #CC="$CC -no-cpp-precomp" # Select appropriate semaphore support USE_NAMED_POSIX_SEMAPHORES=1 # tools/thread/thread_test must be run THREAD_SUPPORT=yes THREAD_CPPFLAGS="-D_REENTRANT -D_THREAD_SAFE -D_POSIX_PTHREAD_SEMANTICS" THREAD_LIBS="-lpthread" STRERROR_THREADSAFE=yes GETPWUID_THREADSAFE=yes GETHOSTBYNAME_THREADSAFE=yes #NEED_REENTRANT_FUNCS=yes
wespvp@syntegra.com wrote: > On 4/23/04 6:59 PM, "Bruce Momjian" <pgman@candle.pha.pa.us> wrote: > > > > > I have just commited to CVS code that will do all the compile/library > > flags and thread tests automatically. Let me know how it works for > > you. Thanks. > > No, I don't think it is right. I did a 'cvs update', then ran 'configure'. > Templates/darwin contains the information below. I don't know if it is > supposed to contain the three *_TREADSAFE lines any more, but shouldn't it > at least have the 'THREAD_SUPPORT' and 'THREAD_LIBS' entries? No, see pgsql/config/acx_pthread.m4. It does the THREAD_LIBS part automatically, and the THREAD_SUPPORT part is gone. We run our thread test as part of configure now. -- Bruce Momjian | http://candle.pha.pa.us pgman@candle.pha.pa.us | (610) 359-1001 + If your life is a hard drive, | 13 Roberts Road + Christ can be your backup. | Newtown Square, Pennsylvania 19073
On 4/24/04 9:15 PM, "Bruce Momjian" <pgman@candle.pha.pa.us> wrote: > No, see pgsql/config/acx_pthread.m4. It does the THREAD_LIBS part > automatically, and the THREAD_SUPPORT part is gone. We run our thread > test as part of configure now. I must be missing something. I don't see a -lpthread anywhere. The libpq linking is: gcc -no-cpp-precomp -O2 -fno-strict-aliasing -Wall -Wmissing-prototypes -Wmissing-declarations -bundle fe-auth.o fe-connect.o fe-exec.o fe-misc.o fe-print.o fe-lobj.o fe-protocol2.o fe-protocol3.o pqexpbuffer.o pqsignal.o fe-secure.o dllist.o md5.o ip.o wchar.o encnames.o noblock.o path.o thread.o -L../../../src/port -lssl -lcrypto -lkrb5 -lresolv -D_REENTRANT -D_THREAD_SAFE -D_POSIX_PTHREAD_SEMANTICS -o libpq.so.3.2 How can this be linking in thread support without -lpthread? Wes
wespvp@syntegra.com wrote: > On 4/24/04 9:15 PM, "Bruce Momjian" <pgman@candle.pha.pa.us> wrote: > > > No, see pgsql/config/acx_pthread.m4. It does the THREAD_LIBS part > > automatically, and the THREAD_SUPPORT part is gone. We run our thread > > test as part of configure now. > > I must be missing something. I don't see a -lpthread anywhere. The libpq > linking is: > > gcc -no-cpp-precomp -O2 -fno-strict-aliasing -Wall -Wmissing-prototypes > -Wmissing-declarations -bundle fe-auth.o fe-connect.o fe-exec.o fe-misc.o > fe-print.o fe-lobj.o fe-protocol2.o fe-protocol3.o pqexpbuffer.o pqsignal.o > fe-secure.o dllist.o md5.o ip.o wchar.o encnames.o noblock.o path.o thread.o > -L../../../src/port -lssl -lcrypto -lkrb5 -lresolv -D_REENTRANT > -D_THREAD_SAFE -D_POSIX_PTHREAD_SEMANTICS -o libpq.so.3.2 > > How can this be linking in thread support without -lpthread? In config/acx_pthreasd.m4, I see: acx_pthread_flags="pthreads none -Kthread -kthread lthread \ -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-conf ... The configure test should be trying -lpthread as part of its work. Can you check config.log to see why it is failing? Here is the code that should be checking: *) AC_MSG_CHECKING([for the pthreads library -l$flag]) PTHREAD_LIBS="-l$flag" I don't have any flags here so I can't test that. Maybe I should try on FreeBSd. Also, I am not happy the -D flags appear after the C files. I might need to fix that in the Makefiles. -- Bruce Momjian | http://candle.pha.pa.us pgman@candle.pha.pa.us | (610) 359-1001 + If your life is a hard drive, | 13 Roberts Road + Christ can be your backup. | Newtown Square, Pennsylvania 19073
On 4/25/04 8:57 AM, "Bruce Momjian" <pgman@candle.pha.pa.us> wrote: > In config/acx_pthreasd.m4, I see: > > acx_pthread_flags="pthreads none -Kthread -kthread lthread \ > -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-conf > ... > > The configure test should be trying -lpthread as part of its work. > > Can you check config.log to see why it is failing? Here is the code > that should be checking: I don't see it attempting that test at all, but could be overlooking it. I'll send you the config.log file. Wes
wespvp@syntegra.com wrote: > On 4/25/04 8:57 AM, "Bruce Momjian" <pgman@candle.pha.pa.us> wrote: > > > In config/acx_pthreasd.m4, I see: > > > > acx_pthread_flags="pthreads none -Kthread -kthread lthread \ > > -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-conf > > ... > > > > The configure test should be trying -lpthread as part of its work. > > > > Can you check config.log to see why it is failing? Here is the code > > that should be checking: > > I don't see it attempting that test at all, but could be overlooking it. > I'll send you the config.log file. OK, I just did some major wacking of the thread stuff and tried it on FreeBSD 4.9. It failed because getpwuid() isn't thread-safe on that platform, and there isn't a getpwuid_r() function, but it did pick up -pthread as a valid option. Please test CVS HEAD and report back. Thanks. -- Bruce Momjian | http://candle.pha.pa.us pgman@candle.pha.pa.us | (610) 359-1001 + If your life is a hard drive, | 13 Roberts Road + Christ can be your backup. | Newtown Square, Pennsylvania 19073
On 4/25/04 4:21 PM, "Bruce Momjian" <pgman@candle.pha.pa.us> wrote: > OK, I just did some major wacking of the thread stuff and tried it on > FreeBSD 4.9. It failed because getpwuid() isn't thread-safe on that > platform, and there isn't a getpwuid_r() function, but it did pick up > -pthread as a valid option. > > Please test CVS HEAD and report back. Thanks. No, I still don't see a -lpthread anywhere. Since it successfully builds (i.e. no unsatisfied externals for thread support), that would seem to indicate it isn't building any thread support, wouldn't it? I'll send you the latest config.out Wes
> OK, I just did some major wacking of the thread stuff and tried it on > FreeBSD 4.9. It failed because getpwuid() isn't thread-safe on that > platform, and there isn't a getpwuid_r() function, but it did pick up > -pthread as a valid option. > > Please test CVS HEAD and report back. Thanks. Maybe -lpthread isn't needed on OS X (10.3)? I built thread_test, which compiled without -lpthread and still worked. How can I be certain postgresql built correctly with full thread support? % make gcc -no-cpp-precomp -O2 -fno-strict-aliasing -Wall -Wmissing-prototypes -Wmissing-declarations -D_REENTRANT -D_THREAD_SAFE -D_POSIX_PTHREAD_SEMANTICS -I../../../src/include -c -o thread_test.o thread_test.c -MMD gcc -no-cpp-precomp -O2 -fno-strict-aliasing -Wall -Wmissing-prototypes -Wmissing-declarations -D_REENTRANT -D_THREAD_SAFE -D_POSIX_PTHREAD_SEMANTICS -L../../../src/port thread_test.o -o thread_test % otool -L thread_test (Apple technote says this is the same as "ldd") thread_test: /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 71.0.0) % ./thread_test Your errno is thread-safe. Your system has sterror_r(); it does not need strerror(). Your system has getpwuid_r(); it does not need getpwuid(). Your system has getaddrinfo(); it does not need gethostbyname() or gethostbyname_r(). Your platform is thread-safe.