mirror of git://git.musl-libc.org/musl
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.
This commit is contained in:
parent
370f78f2c8
commit
0bed7e0acf
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue