Unblock stalled i/o signals on windows

This commit is contained in:
Justine Tunney 2024-12-29 00:05:59 -08:00
parent aca4214ff6
commit 9ba5b227d9
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
4 changed files with 43 additions and 50 deletions

View file

@ -660,7 +660,7 @@ static void *__mmap_impl(char *addr, size_t size, int prot, int flags, int fd,
if (!IsWindows()) { if (!IsWindows()) {
struct Map *deleted = 0; struct Map *deleted = 0;
__maps_lock(); __maps_lock();
if (IsWindows() || fixedmode) if (fixedmode)
if (__muntrack(res.addr, size, &deleted, 0, 0)) if (__muntrack(res.addr, size, &deleted, 0, 0))
STRACE("memtrack compromised by hole punch oom"); STRACE("memtrack compromised by hole punch oom");
__maps_insert(map); __maps_insert(map);

View file

@ -492,9 +492,8 @@ textwindows void __sig_generate(int sig, int sic) {
__sig_terminate(sig); __sig_terminate(sig);
} }
if (atomic_load_explicit(__sig.process, memory_order_acquire) & if (atomic_load_explicit(__sig.process, memory_order_acquire) &
(1ull << (sig - 1))) { (1ull << (sig - 1)))
return; return;
}
_pthread_lock(); _pthread_lock();
for (e = dll_first(_pthread_list); e; e = dll_next(_pthread_list, e)) { for (e = dll_first(_pthread_list); e; e = dll_next(_pthread_list, e)) {
pt = POSIXTHREAD_CONTAINER(e); pt = POSIXTHREAD_CONTAINER(e);
@ -503,9 +502,8 @@ textwindows void __sig_generate(int sig, int sic) {
continue; continue;
// we don't want to signal a thread that isn't running // we don't want to signal a thread that isn't running
if (atomic_load_explicit(&pt->pt_status, memory_order_acquire) >= if (atomic_load_explicit(&pt->pt_status, memory_order_acquire) >=
kPosixThreadTerminated) { kPosixThreadTerminated)
continue; continue;
}
// choose this thread if it isn't masking sig // choose this thread if it isn't masking sig
if (!(atomic_load_explicit(&pt->tib->tib_sigmask, memory_order_acquire) & if (!(atomic_load_explicit(&pt->tib->tib_sigmask, memory_order_acquire) &
(1ull << (sig - 1)))) { (1ull << (sig - 1)))) {
@ -756,11 +754,26 @@ HAIRY static uint32_t __sig_worker(void *arg) {
__sig_generate(sig, SI_KERNEL); __sig_generate(sig, SI_KERNEL);
} }
// unblock stalled i/o signals in threads
_pthread_lock();
for (struct Dll *e = dll_first(_pthread_list); e;
e = dll_next(_pthread_list, e)) {
struct PosixThread *pt = POSIXTHREAD_CONTAINER(e);
if (atomic_load_explicit(&pt->pt_status, memory_order_acquire) >=
kPosixThreadTerminated)
break;
if (atomic_load_explicit(&pt->pt_blocker, memory_order_acquire) &&
(atomic_load_explicit(&pt->tib->tib_sigpending,
memory_order_acquire) &
~atomic_load_explicit(&pt->pt_blkmask, memory_order_acquire)))
__sig_wake(pt, 0);
}
_pthread_unlock();
// unblock stalled asynchronous signals in threads // unblock stalled asynchronous signals in threads
struct PosixThread *mark;
for (;;) { for (;;) {
sigset_t pending, mask; sigset_t pending, mask;
mark = 0; struct PosixThread *mark = 0;
_pthread_lock(); _pthread_lock();
for (struct Dll *e = dll_first(_pthread_list); e; for (struct Dll *e = dll_first(_pthread_list); e;
e = dll_next(_pthread_list, e)) { e = dll_next(_pthread_list, e)) {
@ -790,6 +803,7 @@ HAIRY static uint32_t __sig_worker(void *arg) {
pending &= ~(1ull << (sig - 1)); pending &= ~(1ull << (sig - 1));
__sig_killer(mark, sig, SI_KERNEL); __sig_killer(mark, sig, SI_KERNEL);
} }
_pthread_unref(mark);
} }
// wait until next scheduler quantum // wait until next scheduler quantum

View file

@ -1,27 +1,20 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ // Copyright 2024 Justine Alexandra Roberts Tunney
vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi //
// Permission to use, copy, modify, and/or distribute this software for
Copyright 2023 Justine Alexandra Roberts Tunney // any purpose with or without fee is hereby granted, provided that the
// above copyright notice and this permission notice appear in all copies.
Permission to use, copy, modify, and/or distribute this software for //
any purpose with or without fee is hereby granted, provided that the // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
above copyright notice and this permission notice appear in all copies. // WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL // AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED // DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE // PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL // TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR // PERFORMANCE OF THIS SOFTWARE.
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR #include <signal.h>
PERFORMANCE OF THIS SOFTWARE. #include <unistd.h>
*/
#include "libc/calls/calls.h"
#include "libc/calls/struct/sigaction.h"
#include "libc/calls/struct/sigset.h"
#include "libc/dce.h"
#include "libc/sysv/consts/sa.h"
#include "libc/sysv/consts/sig.h"
volatile int handler_invoked; volatile int handler_invoked;
@ -33,24 +26,17 @@ int main() {
sigset_t mask, oldmask; sigset_t mask, oldmask;
struct sigaction sa, current_sa; struct sigaction sa, current_sa;
if (IsWindows()) {
// TODO(jart): support non-fatal signals between processes
return 0;
}
sa.sa_handler = signal_handler; sa.sa_handler = signal_handler;
sa.sa_flags = SA_RESETHAND; sa.sa_flags = SA_RESETHAND;
sigemptyset(&sa.sa_mask); sigemptyset(&sa.sa_mask);
if (sigaction(SIGINT, &sa, 0) == -1) { if (sigaction(SIGINT, &sa, 0) == -1)
return 1; return 1;
}
sigemptyset(&mask); sigemptyset(&mask);
sigaddset(&mask, SIGINT); sigaddset(&mask, SIGINT);
if (sigprocmask(SIG_BLOCK, &mask, &oldmask) == -1) { if (sigprocmask(SIG_BLOCK, &mask, &oldmask) == -1)
return 2; return 2;
}
int pid = fork(); int pid = fork();
if (pid == -1) { if (pid == -1) {
@ -60,15 +46,12 @@ int main() {
return 0; return 0;
} else { } else {
sigsuspend(&oldmask); sigsuspend(&oldmask);
if (!handler_invoked) { if (!handler_invoked)
return 4; return 4;
} if (sigaction(SIGINT, 0, &current_sa) == -1)
if (sigaction(SIGINT, 0, &current_sa) == -1) {
return 5; return 5;
} if (current_sa.sa_handler != SIG_DFL)
if (current_sa.sa_handler != SIG_DFL) {
return 6; return 6;
}
return 0; return 0;
} }
} }

View file

@ -133,10 +133,6 @@ int main() {
if (IsOpenbsd()) if (IsOpenbsd())
return 0; return 0;
// TODO(jart): Why is this test flaky on Windows?
if (IsWindows())
return 0;
// Block SIGUSR1 and SIGUSR2 in main thread // Block SIGUSR1 and SIGUSR2 in main thread
sigset_t block_set; sigset_t block_set;
sigemptyset(&block_set); sigemptyset(&block_set);