match glibc/lsb cancellation abi on i386
[musl] / src / thread / pthread_create.c
index 17a47f6..9f22b4c 100644 (file)
@@ -1,5 +1,10 @@
 #include "pthread_impl.h"
 
+#ifdef __pthread_unwind_next
+#undef __pthread_unwind_next
+#define __pthread_unwind_next __pthread_unwind_next_3
+#endif
+
 void __pthread_unwind_next(struct __ptcb *cb)
 {
        int i, j, not_finished;
@@ -42,6 +47,12 @@ void __pthread_unwind_next(struct __ptcb *cb)
 static void docancel(struct pthread *self)
 {
        struct __ptcb cb = { .__next = self->cancelbuf };
+       sigset_t set;
+       self->canceldisable = 1;
+       self->cancelasync = 0;
+       sigemptyset(&set);
+       sigaddset(&set, SIGCANCEL);
+       __libc_sigprocmask(SIG_UNBLOCK, &set, 0);
        __pthread_unwind_next(&cb);
 }
 
@@ -50,17 +61,17 @@ static void cancel_handler(int sig, siginfo_t *si, void *ctx)
        struct pthread *self = __pthread_self();
        if (si->si_code > 0 || si->si_pid != self->pid) return;
        self->cancel = 1;
-       if (self->canceldisable || (!self->cancelasync && !self->cancelpoint))
-               return;
-       docancel(self);
+       if (self->canceldisable) return;
+       if (self->cancelasync || (self->cancelpoint==1 && PC_AT_SYS(ctx)))
+               docancel(self);
 }
 
 static void cancelpt(int x)
 {
        struct pthread *self = __pthread_self();
        if (self->canceldisable) return;
-       self->cancelpoint = x;
-       if (self->cancel) docancel(self);
+       if ((self->cancelpoint+=x)==1 && x>=0 && self->cancel)
+               docancel(self);
 }
 
 /* "rsyscall" is a mechanism by which a thread can synchronously force all