This is the mail archive of the glibc-linux@ricardo.ecn.wfu.edu mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Potential LinuxThreads bug


This is a patch I already sent via glibcbug, but I'm just repeating it here.
What it does is guard the caller of __pthread_lock against spurious wakeup
which would fool it into thinking it has the lock.

This can actually happen: for example, the thread is on a CV queue,
and is then cancelled. It wants the lock to the CV queue so it can
remove itself, but has to wait. Another thread broadcasts the condition,
thus waking up the sleeping thread. That thread now returns
from __pthread_lock, thinking it has the lock.

Here is the patch which closes the hole. The solution is for the thread
to simply check its p_nextlock link. If it's not null, it's still on the
lock queue and needs to go back to sleep, ignoring the spurious wakeup.
The unlock code already sets the link pointer to null when it wakes
the thread.

The spurious wakeup might not be an actual problem, but it is easier
to remove suspicion by patching the hole than to try to prove that
it's not a problem.

Comments?

diff -urNp linuxthreads-ORIG/internals.h linuxthreads/internals.h
--- linuxthreads-ORIG/internals.h	Fri Jul 16 16:18:19 1999
+++ linuxthreads/internals.h	Thu Dec  9 11:19:18 1999
@@ -75,6 +75,7 @@ struct _pthread_descr_struct {
                                 /* Double chaining of active threads */
   pthread_descr p_nextwaiting;  /* Next element in the queue holding the thr */
   pthread_descr p_nextlock;	/* can be on a queue and waiting on a lock */
+                                /* null value means "not waiting on lock" */
   pthread_t p_tid;              /* Thread identifier */
   int p_pid;                    /* PID of Unix process */
   int p_priority;               /* Thread priority (== 0 if not realtime) */
diff -urNp linuxthreads-ORIG/spinlock.c linuxthreads/spinlock.c
--- linuxthreads-ORIG/spinlock.c	Fri Jul  9 13:56:04 1999
+++ linuxthreads/spinlock.c	Thu Dec  9 11:52:06 1999
@@ -56,7 +56,11 @@ void internal_function __pthread_lock(st
     }
   } while(! compare_and_swap(&lock->__status, oldstatus, newstatus,
                              &lock->__spinlock));
-  if (oldstatus != 0) suspend(self);
+  if (oldstatus != 0) {
+    do {
+      suspend(self);
+    } while (self->p_nextlock != NULL); /* guard against spurious wakeup */
+  }
 }
 
 void internal_function __pthread_unlock(struct _pthread_fastlock * lock)


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]