From 971bc8147fb88f90414466d44f145f30ecfd1ba0 Mon Sep 17 00:00:00 2001 From: Justine Tunney Date: Thu, 28 Jan 2021 15:49:15 -0800 Subject: [PATCH] Check for EINTR in poll$nt() This is a bandaid that lets CTRL-C work in daemons until a better solution for signals on Windows can be implemented. --- libc/calls/g_sighandrvas.c | 2 +- libc/calls/hefty/fork-nt.c | 4 ++-- libc/calls/internal.h | 3 ++- libc/calls/interrupted.c | 21 +++++++++++++++++++++ libc/calls/onntconsoleevent.c | 22 ++++++++++++++++++---- libc/calls/sigaction.c | 4 ++-- libc/calls/sigenter.S | 2 +- libc/sock/poll-nt.c | 2 ++ tool/build/runitd.c | 10 +++++++++- 9 files changed, 58 insertions(+), 12 deletions(-) create mode 100644 libc/calls/interrupted.c diff --git a/libc/calls/g_sighandrvas.c b/libc/calls/g_sighandrvas.c index 44be8da75cc..ed01f3aa446 100644 --- a/libc/calls/g_sighandrvas.c +++ b/libc/calls/g_sighandrvas.c @@ -18,4 +18,4 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/internal.h" -hidden int g_sighandrvas[NSIG]; +unsigned __sighandrvas[NSIG]; diff --git a/libc/calls/hefty/fork-nt.c b/libc/calls/hefty/fork-nt.c index a511e87902e..613b1a7a5b0 100644 --- a/libc/calls/hefty/fork-nt.c +++ b/libc/calls/hefty/fork-nt.c @@ -141,8 +141,8 @@ textwindows int fork$nt(void) { &startinfo, &procinfo) != -1) { CloseHandle(reader); CloseHandle(procinfo.hThread); - if (weaken(g_sighandrvas) && - weaken(g_sighandrvas)[SIGCHLD] == SIG_IGN) { + if (weaken(__sighandrvas) && + weaken(__sighandrvas)[SIGCHLD] == SIG_IGN) { CloseHandle(procinfo.hProcess); } else { g_fds.p[pid].kind = kFdProcess; diff --git a/libc/calls/internal.h b/libc/calls/internal.h index d7189eb0155..d3c8ea7f134 100644 --- a/libc/calls/internal.h +++ b/libc/calls/internal.h @@ -60,8 +60,9 @@ struct Fds { extern const struct Fd kEmptyFd; +hidden extern volatile bool __interrupted; hidden extern int __vforked; -hidden extern int g_sighandrvas[NSIG]; +hidden extern unsigned __sighandrvas[NSIG]; hidden extern struct Fds g_fds; hidden extern struct NtSystemInfo g_ntsysteminfo; hidden extern struct NtStartupInfo g_ntstartupinfo; diff --git a/libc/calls/interrupted.c b/libc/calls/interrupted.c new file mode 100644 index 00000000000..3362c4e6234 --- /dev/null +++ b/libc/calls/interrupted.c @@ -0,0 +1,21 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2021 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/calls/internal.h" + +volatile bool __interrupted; diff --git a/libc/calls/onntconsoleevent.c b/libc/calls/onntconsoleevent.c index b03347aee73..35e20cc7bc4 100644 --- a/libc/calls/onntconsoleevent.c +++ b/libc/calls/onntconsoleevent.c @@ -19,12 +19,15 @@ #include "libc/bits/pushpop.h" #include "libc/calls/internal.h" #include "libc/calls/struct/siginfo.h" +#include "libc/calls/typedef/sigaction_f.h" #include "libc/nt/enum/ctrlevent.h" +#include "libc/nt/runtime.h" #include "libc/str/str.h" #include "libc/sysv/consts/sig.h" textwindows bool32 __onntconsoleevent(uint32_t CtrlType) { int sig; + unsigned rva; siginfo_t info; switch (CtrlType) { case kNtCtrlCEvent: @@ -43,8 +46,19 @@ textwindows bool32 __onntconsoleevent(uint32_t CtrlType) { default: return false; } - memset(&info, 0, sizeof(info)); - info.si_signo = sig; - __sigenter(sig, &info, NULL); - return true; + switch ((rva = __sighandrvas[sig])) { + case (uintptr_t)SIG_DFL: + dprintf(2, "__onntconsoleevent ExitProcess\n"); + ExitProcess(128 + sig); + case (uintptr_t)SIG_IGN: + dprintf(2, "__onntconsoleevent SIG_IGN\n"); + return true; + default: + dprintf(2, "__onntconsoleevent %#x\n", rva); + memset(&info, 0, sizeof(info)); + info.si_signo = sig; + ((sigaction_f)(_base + rva))(sig, &info, NULL); + __interrupted = true; + return true; + } } diff --git a/libc/calls/sigaction.c b/libc/calls/sigaction.c index d134aba8d98..5a6b94f1b5f 100644 --- a/libc/calls/sigaction.c +++ b/libc/calls/sigaction.c @@ -179,12 +179,12 @@ int(sigaction)(int sig, const struct sigaction *act, struct sigaction *oldact) { } if (rc != -1) { if (oldact) { - oldrva = g_sighandrvas[sig]; + oldrva = __sighandrvas[sig]; oldact->sa_sigaction = (sigaction_f)( oldrva < kSigactionMinRva ? oldrva : (intptr_t)&_base + oldrva); } if (act) { - g_sighandrvas[sig] = rva; + __sighandrvas[sig] = rva; } } return rc; diff --git a/libc/calls/sigenter.S b/libc/calls/sigenter.S index 6f606403dde..0a28fb5ccfe 100644 --- a/libc/calls/sigenter.S +++ b/libc/calls/sigenter.S @@ -35,7 +35,7 @@ __sigenter: mov %rsp,%rbp .profilable and $NSIG-1,%edi - mov g_sighandrvas(,%rdi,4),%eax + mov __sighandrvas(,%rdi,4),%eax cmp $kSigactionMinRva,%eax jl 2f lea _base(%rax),%eax diff --git a/libc/sock/poll-nt.c b/libc/sock/poll-nt.c index 825d408070c..b9c5e68b4eb 100644 --- a/libc/sock/poll-nt.c +++ b/libc/sock/poll-nt.c @@ -16,6 +16,7 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/bits/bits.h" #include "libc/calls/internal.h" #include "libc/macros.h" #include "libc/nt/struct/pollfd.h" @@ -37,6 +38,7 @@ textwindows int poll$nt(struct pollfd *fds, uint64_t nfds, uint64_t timeoutms) { ntfds[i].events = fds[i].events & (POLLPRI | POLLIN | POLLOUT); } for (;;) { + if (cmpxchg(&__interrupted, true, false)) return eintr(); waitfor = MIN(1000, timeoutms); /* for ctrl+c */ if ((got = WSAPoll(ntfds, nfds, waitfor)) != -1) { if (!got && (timeoutms -= waitfor)) continue; diff --git a/tool/build/runitd.c b/tool/build/runitd.c index b5dca0fc257..808698a8e82 100644 --- a/tool/build/runitd.c +++ b/tool/build/runitd.c @@ -98,11 +98,16 @@ #define kLogMaxBytes (2 * 1000 * 1000) char *g_exepath; +volatile bool g_interrupted; struct sockaddr_in g_servaddr; unsigned char g_buf[PAGESIZE]; bool g_daemonize, g_sendready; int g_timeout, g_devnullfd, g_servfd, g_clifd, g_exefd; +void OnInterrupt(int sig) { + g_interrupted = true; +} + void OnChildTerminated(int sig) { int ws, pid; for (;;) { @@ -359,6 +364,7 @@ int Poll(void) { int i, wait, evcount; struct pollfd fds[1]; TryAgain: + if (g_interrupted) return 0; fds[0].fd = g_servfd; fds[0].events = POLLIN; wait = MIN(1000, g_timeout); @@ -377,12 +383,14 @@ int Poll(void) { int Serve(void) { StartTcpServer(); + sigaction(SIGINT, (&(struct sigaction){.sa_handler = (void *)OnInterrupt}), + NULL); sigaction(SIGCHLD, (&(struct sigaction){.sa_handler = (void *)OnChildTerminated, .sa_flags = SA_RESTART}), NULL); for (;;) { - if (!Poll() && !g_timeout) break; + if (!Poll() && (!g_timeout || g_interrupted)) break; } close(g_servfd); LOGF("timeout expired, shutting down");