aboutsummaryrefslogtreecommitdiff
path: root/nptl/libc-cancellation.c
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2009-05-15 20:42:36 -0700
committerUlrich Drepper <drepper@redhat.com>2009-05-15 20:42:36 -0700
commit9437b427cec6266abd303983848549a5c4ba0d0a (patch)
tree7d3c7df6abb9a33d4f35a3dc20baa59ff1a53ea1 /nptl/libc-cancellation.c
parentbbc5d74dd0bd1c3dbe7ea8515f081dc7e318272c (diff)
downloadglibc-9437b427cec6266abd303983848549a5c4ba0d0a.zip
glibc-9437b427cec6266abd303983848549a5c4ba0d0a.tar.gz
glibc-9437b427cec6266abd303983848549a5c4ba0d0a.tar.bz2
Fix change to prevent cancel signal in unsafe places.
The bits tested to decide when to delay the return when switching off async cancel mode were wrong. Fix that. Also close a race condition in pthread_cancel where the bit indicating the cancellation is unconditionally set even if the cancel type might have changed.
Diffstat (limited to 'nptl/libc-cancellation.c')
-rw-r--r--nptl/libc-cancellation.c8
1 files changed, 2 insertions, 6 deletions
diff --git a/nptl/libc-cancellation.c b/nptl/libc-cancellation.c
index 35ac82b..cada464 100644
--- a/nptl/libc-cancellation.c
+++ b/nptl/libc-cancellation.c
@@ -88,10 +88,6 @@ __libc_disable_asynccancel (int oldtype)
struct pthread *self = THREAD_SELF;
int newval;
-#ifdef THREAD_ATOMIC_AND
- THREAD_ATOMIC_AND (self, cancelhandling, ~CANCELTYPE_BITMASK);
- newval = THREAD_GETMEM (self, cancelhandling);
-#else
int oldval = THREAD_GETMEM (self, cancelhandling);
while (1)
@@ -109,13 +105,13 @@ __libc_disable_asynccancel (int oldtype)
/* Prepare the next round. */
oldval = curval;
}
-#endif
/* We cannot return when we are being canceled. Upon return the
thread might be things which would have to be undone. The
following loop should loop until the cancellation signal is
delivered. */
- while (__builtin_expect (newval & CANCELED_BITMASK, 0))
+ while (__builtin_expect ((newval & (CANCELING_BITMASK | CANCELED_BITMASK))
+ == CANCELING_BITMASK, 0))
{
lll_futex_wait (&self->cancelhandling, newval, LLL_PRIVATE);
newval = THREAD_GETMEM (self, cancelhandling);