diff --git a/libc/calls/park.c b/libc/calls/park.c index e6fa668ee7b..2d5cce9b893 100644 --- a/libc/calls/park.c +++ b/libc/calls/park.c @@ -19,6 +19,7 @@ #include "libc/calls/internal.h" #include "libc/calls/sig.internal.h" #include "libc/intrin/atomic.h" +#include "libc/intrin/weaken.h" #include "libc/nt/synchronization.h" #include "libc/sysv/consts/sicode.h" #include "libc/sysv/errfuns.h" @@ -30,9 +31,11 @@ // raises ECANCELED if this POSIX thread was canceled in masked mode static textwindows int _park_thread(uint32_t msdelay, sigset_t waitmask, bool restartable) { - int sig; + int sig, handler_was_called; if (_check_cancel() == -1) return -1; - if ((sig = __sig_get(waitmask))) goto HandleSignal; + if (_weaken(__sig_get) && (sig = _weaken(__sig_get)(waitmask))) { + goto HandleSignal; + } int expect = 0; atomic_int futex = 0; struct PosixThread *pt = _pthread_self(); @@ -40,9 +43,9 @@ static textwindows int _park_thread(uint32_t msdelay, sigset_t waitmask, atomic_store_explicit(&pt->pt_blocker, &futex, memory_order_release); bool32 ok = WaitOnAddress(&futex, &expect, sizeof(int), msdelay); atomic_store_explicit(&pt->pt_blocker, 0, memory_order_release); - if (ok && (sig = __sig_get(waitmask))) { + if (ok && _weaken(__sig_get) && (sig = _weaken(__sig_get)(waitmask))) { HandleSignal: - int handler_was_called = __sig_relay(sig, SI_KERNEL, waitmask); + handler_was_called = _weaken(__sig_relay)(sig, SI_KERNEL, waitmask); if (_check_cancel() == -1) return -1; if (!restartable || (handler_was_called & SIG_HANDLED_NO_RESTART)) { return eintr(); diff --git a/libc/calls/read-nt.c b/libc/calls/read-nt.c index 8ffe0a34635..55f7ca2165b 100644 --- a/libc/calls/read-nt.c +++ b/libc/calls/read-nt.c @@ -31,6 +31,7 @@ #include "libc/intrin/dll.h" #include "libc/intrin/nomultics.internal.h" #include "libc/intrin/strace.internal.h" +#include "libc/intrin/weaken.h" #include "libc/macros.internal.h" #include "libc/nt/console.h" #include "libc/nt/createfile.h" @@ -721,7 +722,9 @@ static textwindows int WaitForConsole(struct Fd *f, sigset_t waitmask) { } if (_check_cancel() == -1) return -1; if (f->flags & _O_NONBLOCK) return eagain(); - if ((sig = __sig_get(waitmask))) goto DeliverSignal; + if (_weaken(__sig_get) && (sig = _weaken(__sig_get)(waitmask))) { + goto DeliverSignal; + } struct PosixThread *pt = _pthread_self(); pt->pt_blkmask = waitmask; pt->pt_semaphore = sem = CreateSemaphore(0, 0, 1, 0); @@ -732,11 +735,13 @@ static textwindows int WaitForConsole(struct Fd *f, sigset_t waitmask) { if (wi == kNtWaitTimeout) return 0; // vtime elapsed if (wi == 0) return -2; // console data if (wi != 1) return __winerr(); // wait failed - if (!(sig = __sig_get(waitmask))) return eintr(); -DeliverSignal: - int handler_was_called = __sig_relay(sig, SI_KERNEL, waitmask); - if (_check_cancel() == -1) return -1; - if (!(handler_was_called & SIG_HANDLED_NO_RESTART)) return -2; + if (_weaken(__sig_get)) { + if (!(sig = _weaken(__sig_get)(waitmask))) return eintr(); + DeliverSignal: + int handler_was_called = _weaken(__sig_relay)(sig, SI_KERNEL, waitmask); + if (_check_cancel() == -1) return -1; + if (!(handler_was_called & SIG_HANDLED_NO_RESTART)) return -2; + } return eintr(); } diff --git a/libc/calls/readwrite-nt.c b/libc/calls/readwrite-nt.c index 095503241db..d5daac2c501 100644 --- a/libc/calls/readwrite-nt.c +++ b/libc/calls/readwrite-nt.c @@ -22,6 +22,7 @@ #include "libc/calls/struct/fd.internal.h" #include "libc/calls/struct/sigset.h" #include "libc/calls/syscall_support-nt.internal.h" +#include "libc/intrin/weaken.h" #include "libc/nt/enum/filetype.h" #include "libc/nt/errors.h" #include "libc/nt/events.h" @@ -82,7 +83,9 @@ sys_readwrite_nt(int fd, void *data, size_t size, ssize_t offset, bool eagained = false; // check for signals and cancelation if (_check_cancel() == -1) return -1; // ECANCELED - if ((sig = __sig_get(waitmask))) goto HandleInterrupt; + if (_weaken(__sig_get) && (sig = _weaken(__sig_get)(waitmask))) { + goto HandleInterrupt; + } // signals have already been fully blocked by caller // perform i/o operation with atomic signal/cancel checking @@ -130,9 +133,9 @@ sys_readwrite_nt(int fd, void *data, size_t size, ssize_t offset, return eagain(); } // otherwise it must be due to a kill() via __sig_cancel() - if ((sig = __sig_get(waitmask))) { + if (_weaken(__sig_relay) && (sig = _weaken(__sig_get)(waitmask))) { HandleInterrupt: - int handler_was_called = __sig_relay(sig, SI_KERNEL, waitmask); + int handler_was_called = _weaken(__sig_relay)(sig, SI_KERNEL, waitmask); if (_check_cancel() == -1) return -1; // possible if we SIGTHR'd // read() is @restartable unless non-SA_RESTART hands were called if (!(handler_was_called & SIG_HANDLED_NO_RESTART)) { diff --git a/libc/calls/sig.c b/libc/calls/sig.c index c6e208e256e..0971b67049a 100644 --- a/libc/calls/sig.c +++ b/libc/calls/sig.c @@ -218,10 +218,12 @@ textwindows int __sig_raise(volatile int sig, int sic) { } textwindows int __sig_relay(int sig, int sic, sigset_t waitmask) { + sigset_t m; int handler_was_called; - sigset_t m = __sig_begin(waitmask); + m = atomic_exchange_explicit(&__get_tls()->tib_sigmask, waitmask, + memory_order_acquire); handler_was_called = __sig_raise(sig, SI_KERNEL); - __sig_finish(m); + atomic_store_explicit(&__get_tls()->tib_sigmask, m, memory_order_release); return handler_was_called; } diff --git a/libc/calls/struct/sigset.internal.h b/libc/calls/struct/sigset.internal.h index 050071d45c4..567ea1728bb 100644 --- a/libc/calls/struct/sigset.internal.h +++ b/libc/calls/struct/sigset.internal.h @@ -15,9 +15,7 @@ COSMOPOLITAN_C_START_ while (0) sigset_t __sig_block(void); -void __sig_finish(sigset_t); void __sig_unblock(sigset_t); -sigset_t __sig_begin(sigset_t); int __sys_sigprocmask(int, const uint64_t *, uint64_t *, uint64_t); int sys_sigprocmask(int, const sigset_t *, sigset_t *); int sys_sigsuspend(const uint64_t *, uint64_t); diff --git a/libc/intrin/sig.c b/libc/intrin/sig.c index d74fb872e5b..e38ff3cc6a4 100644 --- a/libc/intrin/sig.c +++ b/libc/intrin/sig.c @@ -47,12 +47,3 @@ void __sig_unblock(sigset_t m) { sys_sigprocmask(SIG_SETMASK, &m, 0); } } - -textwindows sigset_t __sig_begin(sigset_t waitmask) { - return atomic_exchange_explicit(&__get_tls()->tib_sigmask, waitmask, - memory_order_acquire); -} - -textwindows void __sig_finish(sigset_t m) { - atomic_store_explicit(&__get_tls()->tib_sigmask, m, memory_order_release); -} diff --git a/libc/proc/wait4-nt.c b/libc/proc/wait4-nt.c index 000014a7b08..bfbcaec441e 100644 --- a/libc/proc/wait4-nt.c +++ b/libc/proc/wait4-nt.c @@ -22,6 +22,7 @@ #include "libc/calls/struct/sigset.internal.h" #include "libc/intrin/dll.h" #include "libc/intrin/strace.internal.h" +#include "libc/intrin/weaken.h" #include "libc/nt/enum/wait.h" #include "libc/nt/events.h" #include "libc/nt/runtime.h" @@ -76,8 +77,8 @@ static textwindows int __proc_wait(int pid, int *wstatus, int options, if (_check_cancel() == -1) { return -1; } - if ((sig = __sig_get(waitmask))) { - handler_was_called = __sig_relay(sig, SI_KERNEL, waitmask); + if (_weaken(__sig_get) && (sig = _weaken(__sig_get)(waitmask))) { + handler_was_called = _weaken(__sig_relay)(sig, SI_KERNEL, waitmask); if (_check_cancel() == -1) { return -1; // ECANCELED because SIGTHR was just handled } diff --git a/libc/sock/winsockblock.c b/libc/sock/winsockblock.c index 522d9245e05..cb5353fe8df 100644 --- a/libc/sock/winsockblock.c +++ b/libc/sock/winsockblock.c @@ -20,6 +20,7 @@ #include "libc/calls/sig.internal.h" #include "libc/calls/struct/sigset.h" #include "libc/errno.h" +#include "libc/intrin/weaken.h" #include "libc/nt/enum/wait.h" #include "libc/nt/errors.h" #include "libc/nt/struct/overlapped.h" @@ -42,7 +43,9 @@ __winsock_block(int64_t handle, uint32_t flags, bool nonblock, int rc, sig, reason = 0; uint32_t status, exchanged; if (_check_cancel() == -1) return -1; // ECANCELED - if ((sig = __sig_get(waitmask))) goto HandleInterrupt; + if (_weaken(__sig_get) && (sig = _weaken(__sig_get)(waitmask))) { + goto HandleInterrupt; + } struct NtOverlapped overlap = {.hEvent = WSACreateEvent()}; rc = StartSocketOp(handle, &overlap, &flags, arg); @@ -87,9 +90,9 @@ __winsock_block(int64_t handle, uint32_t flags, bool nonblock, errno = reason; return -1; } - if ((sig = __sig_get(waitmask))) { + if (_weaken(__sig_get) && (sig = _weaken(__sig_get)(waitmask))) { HandleInterrupt: - int handler_was_called = __sig_relay(sig, SI_KERNEL, waitmask); + int handler_was_called = _weaken(__sig_relay)(sig, SI_KERNEL, waitmask); if (_check_cancel() == -1) return -1; if (handler_was_called != 1) goto RestartOperation; }