about summary refs log tree commit diff
path: root/nptl/cancellation.c
diff options
context:
space:
mode:
Diffstat (limited to 'nptl/cancellation.c')
-rw-r--r--nptl/cancellation.c14
1 files changed, 13 insertions, 1 deletions
diff --git a/nptl/cancellation.c b/nptl/cancellation.c
index 81134a679a..4d528cfc2f 100644
--- a/nptl/cancellation.c
+++ b/nptl/cancellation.c
@@ -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);
+    }
 }