Jerry D. Hedden wrote: > [...] > Under 1.5.24, this test always passes. Under 1.5.25, it is > now frequently failing. If I add a debugging call in the > central most loop: > > print("got: $lt exp: $localtime\n"); > > I get the following as typical of the problem: > > 5 perl-current > ./perl -Ilib ext/threads/t/libc.t > 1..11 > ok 1 - use threads > got: Wed Dec 31 20:00:08 1969 exp: Wed Dec 31 19:00:08 1969 > [...] > This shows a 1 hour difference between the expected and > actual results - which looks like a timezone issue. > > As the changes for 1.5.25 include numerous references to > timezone handling changes, I suspect there may be some > re-entrancy bug in those changes.
Corinna Vinschen wrote: > It would be more helpful if you would send self-contained code which > doesn't have to be tweaked to do a test. I'm not a perl developer, so > it took me some time to get it running. I'd also really prefer > testcases in plain C which I can simply run under GDB. Interpreter code > just adds unnecessary complexity. I was working on this when I got your email. Attached. > I assume the perl libs are using localtime_r, right? Otherwise you > can't rely on reentrency nor thread-safety. Anyway, localtime is > supposed to be thread-safe in Cygwin. I believe this is correct. > The only change in 1.5.25 related to localtime is the fact that the > environment variable "TZ" is now left alone by Cygwin. Up to 1.5.24 the > function tzset() (called by localtime()) also sets the environment > variable "TZ", which is apparently incorrect according to POSIX. "TZ" > is used in later calls to decide whether some other code has to be run > or not. > > And exactly that's the problem. Since TZ is now never set, that other > code, which is not thread-safe, is called much more frequent than > necessary. Actually it should only be called once per process, now it's > called once per invocation of tzset(). I've applied a patch to the 1.5.x > branch and will release an updated 1.5.25 in the next couple of days. Hope my test program helps to verify this.
/***** * * Test program that evokes 'localtime'+threads bug * * Build: gcc -o loctim_bug loctim_bug.c * Run: ./loctim_bug.exe * *****/ #include <time.h> #include <pthread.h> #define MAX_THR 25 #define MAX_LOOP 10000 /* Set this to 24 minus your non-DST timezone */ /* For example, EDT = -5, therefore use 19 */ #define EXPECTED 19 void * time_loop(void* data) { int arg = *((int *)data); time_t when = (time_t)arg; int ii; struct tm *tm; struct timespec sleep, remainder; sleep.tv_sec = 0; sleep.tv_nsec = 1000; for (ii=0; ii < MAX_LOOP; ii++) { tm = localtime(&when); if (tm->tm_hour != EXPECTED) printf("BUG in thread %2d: expected: %d got: %d\n", arg, EXPECTED, tm->tm_hour); nanosleep(&sleep, &remainder); } } int main(int argc, char **argv) { int ii; pthread_t p_thread[MAX_THR]; int args[MAX_THR+2]; /* Launch threads */ for (ii=0; ii < 50; ii++) { args[ii] = ii; pthread_create(&p_thread[ii], NULL, time_loop, (void*)&args[ii]); } /* Make sure threads finish */ args[MAX_THR] = MAX_THR; time_loop((void*)&args[MAX_THR]); args[MAX_THR+1] = MAX_THR+1; time_loop((void*)&args[MAX_THR+1]); printf("Done\n"); } /* EOF */
-- Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple Problem reports: http://cygwin.com/problems.html Documentation: http://cygwin.com/docs.html FAQ: http://cygwin.com/faq/