Explorar el Código

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 hace 14 años
padre
commit
0bed7e0acf
Se han modificado 1 ficheros con 9 adiciones y 9 borrados
  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;
 }