On Jan 10, 2008 10:00 PM, Russ Allbery <rra@stanford.edu> wrote:
"Jonathan Leffler" <jonathan.leffler@gmail.com> writes:
Actually, the subject pretty much says it all. In tzcode2007k (also in 2007h), the code in localtime.c is:
[...]
I can't immediately see a justification for the asymmetry in the POSIX specification of these functions, but I could be missing something.
My guess is it's because tzset() sets global variables and hence isn't threadsafe.
I wondered about that...The POSIX specification says: Unlike *localtime*(), the reentrant version is not required to set *tzname*. [image: [Option End]] [TSF <javascript:open_code('TSF')>] [image: [Option Start]] If the reentrant version does not set *tzname*, it shall not set *daylight* and shall not set *timezone*. [image: [Option End]] I interpret that as meaning "it might not call tzset() - but if it does call tzset(), tzset() shall do the whole job, not just part of the job". However, consider the following simple test program ("Black JL:" is my Unix prompt on machine 'black'): Black JL: cat chk-localtime_r.c #include <time.h> #include <stdio.h> int main(void) { struct tm tp; time_t now = time(0); struct tm *tx = localtime_r(&now, &tp); char buffer[30]; if (tx != 0) { char *s = asctime_r(&tp, buffer); printf("%ld = %s", (long)now, s); } return(0); } Black JL: cc -D_XOPEN_SOURCE=500 -D_POSIX_THREAD_SEMANTICS=1 -o chk -I. chk-localtime_r.c libtz.a Black JL: cc -D_XOPEN_SOURCE=500 -D_POSIX_THREAD_SEMANTICS=1 -o chk.syschk-localtime_r.c Black JL: date; ./chk; ./chk.sys Thu Jan 10 22:35:52 PST 2008 1200033352 = Fri Jan 11 06:35:52 2008 1200033352 = Thu Jan 10 22:35:52 2008 Black JL: Using the Olson code (tzcode2007k), the program defaults to UTC (GMT) because tzset() was never called explicitly. Using the System code (Solaris 10), the same program defaults to my local time zone (US/Pacific). So, at least there is a difference between the behaviour of the Solaris library and the Olson library in this respect. I guess the POSIX manual allows this - and the Olson implementation may well choose to implement localtime_r() without tzset() because tzset() is not re-entrant or thread-safe. The POSIX standard says of localtime(), that: CX <javascript:open_code('CX')>] [image: [Option Start]] The *localtime*() function need not be reentrant. A function that is not required to be reentrant is not required to be thread-safe. The same words are not said of tzset() -- which might conceivably be an omission, or it might imply that the function is supposed to be thread-safe and reentrant. -- Jonathan Leffler <jonathan.leffler@gmail.com> #include <disclaimer.h> Guardian of DBD::Informix - v2007.0914 - http://dbi.perl.org "Blessed are we who can laugh at ourselves, for we shall never cease to be amused."