Use tgkill() on Linux and FreeBSD

This eliminates the chance of rare bugs when thread IDs are recycled.
This commit is contained in:
Justine Tunney 2025-01-03 17:27:13 -08:00
parent 97fc2aab41
commit ed6d133a27
No known key found for this signature in database
GPG key ID: BE714B4575D6E328

View file

@ -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;
}