mirror of
git://sourceware.org/git/glibc.git
synced 2025-03-06 20:58:33 +01:00
No cancel signal in unsafe places.
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.
This commit is contained in:
parent
2e180a2622
commit
1a7f254b4b
3 changed files with 32 additions and 2 deletions
|
@ -1,3 +1,9 @@
|
|||
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
|
||||
|
|
|
@ -70,15 +70,17 @@ __pthread_disable_asynccancel (int oldtype)
|
|||
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;
|
||||
|
@ -92,4 +94,14 @@ __pthread_disable_asynccancel (int oldtype)
|
|||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -86,15 +86,17 @@ __libc_disable_asynccancel (int oldtype)
|
|||
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;
|
||||
|
@ -108,6 +110,16 @@ __libc_disable_asynccancel (int oldtype)
|
|||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue