fix some minor issues in cancellation handling patch

signals were wrongly left masked, and cancellability state was not
switched to disabled, during the execution of cleanup handlers.
This commit is contained in:
Rich Felker 2011-04-17 12:09:47 -04:00
parent feee98903c
commit e74664016b
3 changed files with 19 additions and 11 deletions

View File

@ -1,5 +1,13 @@
#include "pthread_impl.h" #include "pthread_impl.h"
void __cancel()
{
pthread_t self = __pthread_self();
self->canceldisable = 1;
self->cancelasync = 0;
pthread_exit(PTHREAD_CANCELED);
}
long __syscall_cp_asm(volatile void *, long, long, long, long, long, long, long); long __syscall_cp_asm(volatile void *, long, long, long, long, long, long, long);
long (__syscall_cp)(long nr, long u, long v, long w, long x, long y, long z) long (__syscall_cp)(long nr, long u, long v, long w, long x, long y, long z)
@ -18,7 +26,7 @@ long (__syscall_cp)(long nr, long u, long v, long w, long x, long y, long z)
r = __syscall_cp_asm(&self->cp_sp, nr, u, v, w, x, y, z); r = __syscall_cp_asm(&self->cp_sp, nr, u, v, w, x, y, z);
self->cp_sp = old_sp; self->cp_sp = old_sp;
self->cp_ip = old_ip; self->cp_ip = old_ip;
if (r == -EINTR && self->cancel) pthread_exit(PTHREAD_CANCELED); if (r == -EINTR && self->cancel) __cancel();
return r; return r;
} }
@ -31,23 +39,23 @@ static void cancel_handler(int sig, siginfo_t *si, void *ctx)
if (!self->cancel || self->canceldisable) return; if (!self->cancel || self->canceldisable) return;
if (self->cancelasync) pthread_exit(PTHREAD_CANCELED); sigaddset(&uc->uc_sigmask, SIGCANCEL);
if (sp != self->cp_sp) { if (self->cancelasync || sp == self->cp_sp && ip <= self->cp_ip) {
if (!sp) return; self->canceldisable = 1;
sigaddset(&uc->uc_sigmask, SIGCANCEL); pthread_sigmask(SIG_SETMASK, &uc->uc_sigmask, 0);
__syscall(SYS_tgkill, self->pid, self->tid, SIGCANCEL); __cancel();
return;
} }
if (ip <= self->cp_ip) pthread_exit(PTHREAD_CANCELED); if (self->cp_sp)
__syscall(SYS_tgkill, self->pid, self->tid, SIGCANCEL);
} }
static void testcancel() static void testcancel()
{ {
pthread_t self = __pthread_self(); pthread_t self = __pthread_self();
if (self->cancel && !self->canceldisable) if (self->cancel && !self->canceldisable)
pthread_exit(PTHREAD_CANCELED); __cancel();
} }
static void init_cancellation() static void init_cancellation()

View File

@ -33,4 +33,4 @@ __syscall_cp_asm:
movl %eax,4(%ecx) movl %eax,4(%ecx)
movl %eax,(%ecx) movl %eax,(%ecx)
pushl $-1 pushl $-1
call pthread_exit call __cancel

View File

@ -21,4 +21,4 @@ __syscall_cp_asm:
mov %rdi,8(%r10) mov %rdi,8(%r10)
mov %rdi,(%r10) mov %rdi,(%r10)
dec %rdi dec %rdi
jmp pthread_exit jmp __cancel