mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-31 03:27:39 +00:00
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:
parent
d8fffd2123
commit
971bc8147f
9 changed files with 58 additions and 12 deletions
|
@ -18,4 +18,4 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
|
||||
hidden int g_sighandrvas[NSIG];
|
||||
unsigned __sighandrvas[NSIG];
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
21
libc/calls/interrupted.c
Normal file
21
libc/calls/interrupted.c
Normal 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;
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 @@ TryAgain:
|
|||
|
||||
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");
|
||||
|
|
Loading…
Reference in a new issue