Browse Source

fix race condition in raise - just mask signals

a signal handler could fork after the pid/tid were read, causing the
wrong process to be signalled. i'm not sure if this is supposed to
have UB or not, but raise is async-signal-safe, so it probably is
allowed. the current solution is slightly expensive so this
implementation is likely to be changed in the future.
Rich Felker 14 năm trước cách đây
mục cha
commit
0bed7e0acf
1 tập tin đã thay đổi với 9 bổ sung9 xóa
  1. 9 9
      src/signal/raise.c

+ 9 - 9
src/signal/raise.c

@@ -2,17 +2,17 @@
 #include <errno.h>
 #include "syscall.h"
 
+int __sigprocmask(int, const sigset_t *, sigset_t *);
+
 int raise(int sig)
 {
 	int pid, tid, ret;
-	/* Getting the pid/tid pair is not atomic, and could give wrong
-	 * result if a fork occurs in a signal handler between the two
-	 * syscalls. Use the tgkill syscall's ESRCH semantics to detect
-	 * this condition and retry. */
-	do {
-		tid = syscall0(__NR_gettid);
-		pid = syscall0(__NR_getpid);
-		ret = syscall3(__NR_tgkill, pid, tid, sig);
-	} while (ret<0 && errno == ESRCH);
+	sigset_t set;
+	sigfillset(&set);
+	__sigprocmask(SIG_BLOCK, &set, &set);
+	tid = syscall0(__NR_gettid);
+	pid = syscall0(__NR_getpid);
+	ret = syscall3(__NR_tgkill, pid, tid, sig);
+	__sigprocmask(SIG_SETMASK, &set, 0);
 	return ret;
 }