Преглед на файлове

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.
Rich Felker преди 14 години
родител
ревизия
e74664016b
променени са 3 файла, в които са добавени 19 реда и са изтрити 11 реда
  1. 17 9
      src/thread/cancel_impl.c
  2. 1 1
      src/thread/i386/syscall_cp.s
  3. 1 1
      src/thread/x86_64/syscall_cp.s

+ 17 - 9
src/thread/cancel_impl.c

@@ -1,5 +1,13 @@
 #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)(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);
 	self->cp_sp = old_sp;
 	self->cp_ip = old_ip;
-	if (r == -EINTR && self->cancel) pthread_exit(PTHREAD_CANCELED);
+	if (r == -EINTR && self->cancel) __cancel();
 	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->cancelasync) pthread_exit(PTHREAD_CANCELED);
+	sigaddset(&uc->uc_sigmask, SIGCANCEL);
 
-	if (sp != self->cp_sp) {
-		if (!sp) return;
-		sigaddset(&uc->uc_sigmask, SIGCANCEL);
-		__syscall(SYS_tgkill, self->pid, self->tid, SIGCANCEL);
-		return;
+	if (self->cancelasync || sp == self->cp_sp && ip <= self->cp_ip) {
+		self->canceldisable = 1;
+		pthread_sigmask(SIG_SETMASK, &uc->uc_sigmask, 0);
+		__cancel();
 	}
 
-	if (ip <= self->cp_ip) pthread_exit(PTHREAD_CANCELED);
+	if (self->cp_sp)
+		__syscall(SYS_tgkill, self->pid, self->tid, SIGCANCEL);
 }
 
 static void testcancel()
 {
 	pthread_t self = __pthread_self();
 	if (self->cancel && !self->canceldisable)
-		pthread_exit(PTHREAD_CANCELED);
+		__cancel();
 }
 
 static void init_cancellation()

+ 1 - 1
src/thread/i386/syscall_cp.s

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

+ 1 - 1
src/thread/x86_64/syscall_cp.s

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