mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-04-21 06:14:43 +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"
|
#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) {
|
&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;
|
||||||
|
|
|
@ -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
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/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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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");
|
||||||
|
|
Loading…
Add table
Reference in a new issue