Skip to content

Commit

Permalink
No cancel signal in unsafe places.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Ulrich Drepper committed May 15, 2009
1 parent 2e180a2 commit b1e74e1
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 2 deletions.
6 changes: 6 additions & 0 deletions nptl/ChangeLog
Original file line number Diff line number Diff line change
@@ -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
Expand Down
14 changes: 13 additions & 1 deletion nptl/cancellation.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
}
}
14 changes: 13 additions & 1 deletion nptl/libc-cancellation.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
}
}


Expand Down

0 comments on commit b1e74e1

Please sign in to comment.