Jelajahi Sumber

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 tahun lalu
induk
melakukan
e74664016b
3 mengubah file dengan 19 tambahan dan 11 penghapusan
  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