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.
This commit is contained in:
Justine Tunney
2021-01-28 15:49:15 -08:00
parent d8fffd2123
commit 971bc8147f
9 changed files with 58 additions and 12 deletions

View File

@ -18,4 +18,4 @@
╚─────────────────────────────────────────────────────────────────────────────*/ ╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
hidden int g_sighandrvas[NSIG]; unsigned __sighandrvas[NSIG];

View File

@ -141,8 +141,8 @@ textwindows int fork$nt(void) {
&startinfo, &procinfo) != -1) { &startinfo, &procinfo) != -1) {
CloseHandle(reader); CloseHandle(reader);
CloseHandle(procinfo.hThread); CloseHandle(procinfo.hThread);
if (weaken(g_sighandrvas) && if (weaken(__sighandrvas) &&
weaken(g_sighandrvas)[SIGCHLD] == SIG_IGN) { weaken(__sighandrvas)[SIGCHLD] == SIG_IGN) {
CloseHandle(procinfo.hProcess); CloseHandle(procinfo.hProcess);
} else { } else {
g_fds.p[pid].kind = kFdProcess; g_fds.p[pid].kind = kFdProcess;

View File

@ -60,8 +60,9 @@ struct Fds {
extern const struct Fd kEmptyFd; extern const struct Fd kEmptyFd;
hidden extern volatile bool __interrupted;
hidden extern int __vforked; hidden extern int __vforked;
hidden extern int g_sighandrvas[NSIG]; hidden extern unsigned __sighandrvas[NSIG];
hidden extern struct Fds g_fds; hidden extern struct Fds g_fds;
hidden extern struct NtSystemInfo g_ntsysteminfo; hidden extern struct NtSystemInfo g_ntsysteminfo;
hidden extern struct NtStartupInfo g_ntstartupinfo; hidden extern struct NtStartupInfo g_ntstartupinfo;

21
libc/calls/interrupted.c Normal file
View File

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

View File

@ -19,12 +19,15 @@
#include "libc/bits/pushpop.h" #include "libc/bits/pushpop.h"
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/calls/struct/siginfo.h" #include "libc/calls/struct/siginfo.h"
#include "libc/calls/typedef/sigaction_f.h"
#include "libc/nt/enum/ctrlevent.h" #include "libc/nt/enum/ctrlevent.h"
#include "libc/nt/runtime.h"
#include "libc/str/str.h" #include "libc/str/str.h"
#include "libc/sysv/consts/sig.h" #include "libc/sysv/consts/sig.h"
textwindows bool32 __onntconsoleevent(uint32_t CtrlType) { textwindows bool32 __onntconsoleevent(uint32_t CtrlType) {
int sig; int sig;
unsigned rva;
siginfo_t info; siginfo_t info;
switch (CtrlType) { switch (CtrlType) {
case kNtCtrlCEvent: case kNtCtrlCEvent:
@ -43,8 +46,19 @@ textwindows bool32 __onntconsoleevent(uint32_t CtrlType) {
default: default:
return false; return false;
} }
memset(&info, 0, sizeof(info)); switch ((rva = __sighandrvas[sig])) {
info.si_signo = sig; case (uintptr_t)SIG_DFL:
__sigenter(sig, &info, NULL); dprintf(2, "__onntconsoleevent ExitProcess\n");
return true; 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;
}
} }

View File

@ -179,12 +179,12 @@ int(sigaction)(int sig, const struct sigaction *act, struct sigaction *oldact) {
} }
if (rc != -1) { if (rc != -1) {
if (oldact) { if (oldact) {
oldrva = g_sighandrvas[sig]; oldrva = __sighandrvas[sig];
oldact->sa_sigaction = (sigaction_f)( oldact->sa_sigaction = (sigaction_f)(
oldrva < kSigactionMinRva ? oldrva : (intptr_t)&_base + oldrva); oldrva < kSigactionMinRva ? oldrva : (intptr_t)&_base + oldrva);
} }
if (act) { if (act) {
g_sighandrvas[sig] = rva; __sighandrvas[sig] = rva;
} }
} }
return rc; return rc;

View File

@ -35,7 +35,7 @@ __sigenter:
mov %rsp,%rbp mov %rsp,%rbp
.profilable .profilable
and $NSIG-1,%edi and $NSIG-1,%edi
mov g_sighandrvas(,%rdi,4),%eax mov __sighandrvas(,%rdi,4),%eax
cmp $kSigactionMinRva,%eax cmp $kSigactionMinRva,%eax
jl 2f jl 2f
lea _base(%rax),%eax lea _base(%rax),%eax

View File

@ -16,6 +16,7 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │ │ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/ ╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/bits/bits.h"
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/macros.h" #include "libc/macros.h"
#include "libc/nt/struct/pollfd.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); ntfds[i].events = fds[i].events & (POLLPRI | POLLIN | POLLOUT);
} }
for (;;) { for (;;) {
if (cmpxchg(&__interrupted, true, false)) return eintr();
waitfor = MIN(1000, timeoutms); /* for ctrl+c */ waitfor = MIN(1000, timeoutms); /* for ctrl+c */
if ((got = WSAPoll(ntfds, nfds, waitfor)) != -1) { if ((got = WSAPoll(ntfds, nfds, waitfor)) != -1) {
if (!got && (timeoutms -= waitfor)) continue; if (!got && (timeoutms -= waitfor)) continue;

View File

@ -98,11 +98,16 @@
#define kLogMaxBytes (2 * 1000 * 1000) #define kLogMaxBytes (2 * 1000 * 1000)
char *g_exepath; char *g_exepath;
volatile bool g_interrupted;
struct sockaddr_in g_servaddr; struct sockaddr_in g_servaddr;
unsigned char g_buf[PAGESIZE]; unsigned char g_buf[PAGESIZE];
bool g_daemonize, g_sendready; bool g_daemonize, g_sendready;
int g_timeout, g_devnullfd, g_servfd, g_clifd, g_exefd; int g_timeout, g_devnullfd, g_servfd, g_clifd, g_exefd;
void OnInterrupt(int sig) {
g_interrupted = true;
}
void OnChildTerminated(int sig) { void OnChildTerminated(int sig) {
int ws, pid; int ws, pid;
for (;;) { for (;;) {
@ -359,6 +364,7 @@ int Poll(void) {
int i, wait, evcount; int i, wait, evcount;
struct pollfd fds[1]; struct pollfd fds[1];
TryAgain: TryAgain:
if (g_interrupted) return 0;
fds[0].fd = g_servfd; fds[0].fd = g_servfd;
fds[0].events = POLLIN; fds[0].events = POLLIN;
wait = MIN(1000, g_timeout); wait = MIN(1000, g_timeout);
@ -377,12 +383,14 @@ TryAgain:
int Serve(void) { int Serve(void) {
StartTcpServer(); StartTcpServer();
sigaction(SIGINT, (&(struct sigaction){.sa_handler = (void *)OnInterrupt}),
NULL);
sigaction(SIGCHLD, sigaction(SIGCHLD,
(&(struct sigaction){.sa_handler = (void *)OnChildTerminated, (&(struct sigaction){.sa_handler = (void *)OnChildTerminated,
.sa_flags = SA_RESTART}), .sa_flags = SA_RESTART}),
NULL); NULL);
for (;;) { for (;;) {
if (!Poll() && !g_timeout) break; if (!Poll() && (!g_timeout || g_interrupted)) break;
} }
close(g_servfd); close(g_servfd);
LOGF("timeout expired, shutting down"); LOGF("timeout expired, shutting down");