Subj : Either I'm stupid, or NPTL 0.29 on RH9 is broken! To : comp.programming.threads From : Greg Law Date : Tue Jan 25 2005 08:44 am Is there a bug in the following code? It works fine for me on various combinations of Linux distros that I've tried it on, except on RH9. After not too long, all threads except one grind to a halt. compiled simply with: gcc -D_GNU_SOURCE condvars.c (if you want to run it for yourself, I recommend redirecting stderr to /dev/null or a file; If you you look at the stderr output, you can see clearly that one thread is continuously signalling the condvar, and all other threads are blocked waiting for that c.v.!). Interestingly, if I change the "signal" to a broadcast, everything seems to be fine. Also, if you stop the process and restart (via ^z and "fg"), it starts again for a bit, before all but one threads grind to a halt. Which threads continues seems to be random. I've tried this on two different RH9 machines: a dual-Opteron machine (running in 32-bit mode), and a single P4 -- both show the same results. Assuming the code below isn't stupid, then is this a known issue in the shipped NTPL? Here comes the code! _______ #include #include #include #include /* These four are used to implement a hand-crafted mutex */ pthread_cond_t c = PTHREAD_COND_INITIALIZER; pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER; bool avail = true; int waiters; enum {THREAD_COUNT=4}; /* Used to display whether everything is running fine */ char spinners [THREAD_COUNT]; /* This is the key function. */ looper (void*p) { int me = (int)p; while (1) { int do_wake, r; spinners [me]++; r = pthread_mutex_lock (&m); assert_perror (r); /* Can we grab it? */ while (!avail) { /* No, we need to wait */ waiters++; fprintf (stderr, "%ld waits for %d\n", pthread_self(), &c); pthread_cond_wait (&c, &m); waiters--; } /* Yes, we have it */ avail = false; pthread_mutex_unlock(&m); /* Only one thread at a time gets to this point */ fprintf (stderr, "%ld has it!\n", pthread_self()); r = pthread_mutex_lock (&m); assert_perror (r); avail = true; do_wake = waiters; r = pthread_mutex_unlock (&m); assert_perror (r); if (do_wake) { fprintf (stderr, "%ld signals %d\n", pthread_self(), &c); r = pthread_cond_signal (&c); assert_perror (r); } } } int main (void) { int i, r; for (i = 0; i < THREAD_COUNT; i++) { pthread_t tmp; r = pthread_create (&tmp, NULL, looper, (void*)i); assert_perror (r); } while (1) { for (i = 0; i < THREAD_COUNT; i++) printf ("[%c] ", (spinners [i] % 26) + 65); printf ("\r"); fflush (stdout); usleep (10000); } return 0; } .