When disabling async cancellation we cannot return from the function
call if the thread is canceled. This happens when the cancel bits
have been set before async cancel is disabled but the signal hasn't
been sent/received yet. Delay for as long as necessary since
otherwise the signal might be received in an unsafe context.
(cherry picked from commit
1a7f254b4b0590bfab1baa1400705265b1b23b97)
+2009-05-15 Ulrich Drepper <drepper@redhat.com>
+
+ * cancellation.c (__pthread_disable_asynccancel): Don't return if
+ thread is canceled.
+ * libc-cancellation.c (__libc_disable_asynccancel): Likewise.
+
2009-04-27 Ulrich Drepper <drepper@redhat.com>
* cancellation.c (__pthread_disable_asynccancel): Use THREAD_ATOMIC_AND
return;
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)
{
- int newval = oldval & ~CANCELTYPE_BITMASK;
+ newval = oldval & ~CANCELTYPE_BITMASK;
if (newval == oldval)
break;
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))
+ {
+ lll_futex_wait (&self->cancelhandling, newval, LLL_PRIVATE);
+ newval = THREAD_GETMEM (self, cancelhandling);
+ }
}
return;
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)
{
- int newval = oldval & ~CANCELTYPE_BITMASK;
+ newval = oldval & ~CANCELTYPE_BITMASK;
if (newval == oldval)
break;
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))
+ {
+ lll_futex_wait (&self->cancelhandling, newval, LLL_PRIVATE);
+ newval = THREAD_GETMEM (self, cancelhandling);
+ }
}