From ed6d133a27eb297cc97695448bfd3f7eb145670e Mon Sep 17 00:00:00 2001 From: Justine Tunney Date: Fri, 3 Jan 2025 17:27:13 -0800 Subject: [PATCH] Use tgkill() on Linux and FreeBSD This eliminates the chance of rare bugs when thread IDs are recycled. --- libc/thread/pthread_kill.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/libc/thread/pthread_kill.c b/libc/thread/pthread_kill.c index 127c27748..6c1722965 100644 --- a/libc/thread/pthread_kill.c +++ b/libc/thread/pthread_kill.c @@ -24,6 +24,7 @@ #include "libc/intrin/atomic.h" #include "libc/intrin/describeflags.h" #include "libc/intrin/strace.h" +#include "libc/runtime/internal.h" #include "libc/runtime/syslib.internal.h" #include "libc/sysv/consts/sicode.h" #include "libc/thread/posixthread.internal.h" @@ -46,8 +47,12 @@ errno_t pthread_kill(pthread_t thread, int sig) { if (pt) _pthread_ref(pt); if (!thread) { + // avoid crashing on easily predictable npe + // chances are you need a barrier to synchronize startup err = EFAULT; } else if (!(1 <= sig && sig <= 64)) { + // cosmo only supports this many signals + // some platforms have more but we're not sure what they do err = EINVAL; } else if (thread == __get_tls()->tib_pthread) { err = raise(sig); // XNU will EDEADLK it otherwise @@ -60,8 +65,15 @@ errno_t pthread_kill(pthread_t thread, int sig) { if (IsXnuSilicon()) { err = __syslib->__pthread_kill(_pthread_syshand(pt), sig); } else { + int r = 0; int e = errno; - if (sys_tkill(_pthread_tid(pt), sig, pt->tib)) { + int tid = _pthread_tid(pt); + if (IsLinux() || IsFreebsd()) { + r = sys_tgkill(__pid, tid, sig); + } else { + r = sys_tkill(tid, sig, pt->tib); + } + if (r) { err = errno; errno = e; }