fix raise semantics with threads.
authorRich Felker <dalias@aerifal.cx>
Thu, 10 Mar 2011 00:42:06 +0000 (19:42 -0500)
committerRich Felker <dalias@aerifal.cx>
Thu, 10 Mar 2011 00:42:06 +0000 (19:42 -0500)
src/signal/raise.c

index 52f8b428c3bfbdf1c1f3c741fc44be8def8c772f..f437d23f2b4d2a311efb0d96b3ada00373a8a780 100644 (file)
@@ -1,7 +1,18 @@
 #include <signal.h>
+#include <errno.h>
 #include "syscall.h"
 
 int raise(int sig)
 {
-       return __syscall_kill(__syscall_getpid(), 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);
+       return ret;
 }