This is the mail archive of the
libc-alpha@sources.redhat.com
mailing list for the glibc project.
Proposed fix for cancellation bug found by Neal Ferguson.
- To: libc-alpha at sources dot redhat dot com
- Subject: Proposed fix for cancellation bug found by Neal Ferguson.
- From: Kaz Kylheku <kaz at ashi dot footprints dot net>
- Date: Tue, 26 Sep 2000 14:12:10 -0700 (PDT)
A fix is needed because some of the waits, like pthread_join, must not wake
spuriously; due to this bug they will!
A quick way to fix this by changing one place in the code is to hack the
__pthread_set_own_extricate_if function so that it will not store a non-null
pointer if the calling thread's cancellation state is disabled. So the
extricate interface won't actually be registered and so pthread_cancel won't be
able to use it to cause the (spurious) wakeup. Problem solved.
This fix seems clean and appropriate, since this function's job is to abstract
the registration mechanism, which logically belongs to the implementation of
the cancellation module which actually calls the extrication handler.
So, the proposed function (currently in linuxthreads/spinlock.h) looks
something like:
static inline void
__pthread_set_own_extricate_if(pthread_descr self, pthread_extricate_if *peif)
{
/* Only store a non-null peif if the thread has cancellation enabled.
Otherwise pthread_cancel will unconditionally call the extricate handler,
and restart the thread giving rise to forbidden spurious wakeups. */
if (peif == 0 || THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE)
{
/* If we are removing the extricate interface, we need to synchronize
against pthread_cancel so that it does not continue with a pointer
to a deallocated pthread_extricate_if struct! The thread lock
is (ab)used for this synchronization purpose. */
if (peif == 0)
__pthread_lock(THREAD_GETMEM(self, p_lock), self);
THREAD_SETMEM(self, p_extricate, peif);
if (peif == 0)
__pthread_unlock(THREAD_GETMEM (self, p_lock));
}
}
How is that?