Fix flakes in runitd and popen_test

This commit is contained in:
Justine Tunney 2023-07-30 04:26:34 -07:00
parent 801224df67
commit 2ebc5781a1
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
18 changed files with 123 additions and 34 deletions

View file

@ -34,17 +34,27 @@
#include "libc/thread/tls.h" #include "libc/thread/tls.h"
textwindows int _check_interrupts(bool restartable, struct Fd *fd) { textwindows int _check_interrupts(bool restartable, struct Fd *fd) {
int rc; int e, rc;
e = errno;
if (_weaken(pthread_testcancel_np) && if (_weaken(pthread_testcancel_np) &&
(rc = _weaken(pthread_testcancel_np)())) { (rc = _weaken(pthread_testcancel_np)())) {
errno = rc; errno = rc;
return -1; return -1;
} }
if (_weaken(_check_sigalrm)) _weaken(_check_sigalrm)(); if (_weaken(_check_sigalrm)) {
if (!__tls_enabled || !(__get_tls()->tib_flags & TIB_FLAG_TIME_CRITICAL)) { _weaken(_check_sigalrm)();
if (_weaken(_check_sigchld)) _weaken(_check_sigchld)();
if (fd && _weaken(_check_sigwinch)) _weaken(_check_sigwinch)(fd);
} }
if (_weaken(__sig_check) && _weaken(__sig_check)(restartable)) return eintr(); if (!__tls_enabled || !(__get_tls()->tib_flags & TIB_FLAG_TIME_CRITICAL)) {
if (_weaken(_check_sigchld)) {
_weaken(_check_sigchld)();
}
if (fd && _weaken(_check_sigwinch)) {
_weaken(_check_sigwinch)(fd);
}
}
if (_weaken(__sig_check) && _weaken(__sig_check)(restartable)) {
return eintr();
}
errno = e;
return 0; return 0;
} }

View file

@ -479,6 +479,15 @@ static int __sigaction(int sig, const struct sigaction *act,
* frequently calling sigprocmask() out of an abundance of caution, will * frequently calling sigprocmask() out of an abundance of caution, will
* no longer need to pay its outrageous cost. * no longer need to pay its outrageous cost.
* *
* Signal handlers should avoid clobbering global variables like `errno`
* because most signals are asynchronous, i.e. the signal handler might
* be called at any assembly instruction. If something like a `SIGCHLD`
* handler doesn't save / restore the `errno` global when calling wait,
* then any i/o logic in the main program that checks `errno` will most
* likely break. This is rare in practice, since systems usually design
* signals to favor delivery from cancellation points before they block
* however that's not guaranteed.
*
* @return 0 on success or -1 w/ errno * @return 0 on success or -1 w/ errno
* @see xsigaction() for a much better api * @see xsigaction() for a much better api
* @asyncsignalsafe * @asyncsignalsafe

View file

@ -17,12 +17,18 @@
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/nt/createfile.h" #include "libc/nt/createfile.h"
#include "libc/calls/sig.internal.h"
#include "libc/calls/syscall_support-nt.internal.h" #include "libc/calls/syscall_support-nt.internal.h"
#include "libc/intrin/describeflags.internal.h" #include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/strace.internal.h" #include "libc/intrin/strace.internal.h"
#include "libc/nt/errors.h"
#include "libc/nt/runtime.h"
#include "libc/nt/synchronization.h"
#include "libc/nt/thunk/msabi.h" #include "libc/nt/thunk/msabi.h"
__msabi extern typeof(CreateFile) *const __imp_CreateFileW; __msabi extern typeof(CreateFile) *const __imp_CreateFileW;
__msabi extern typeof(GetLastError) *const __imp_GetLastError;
__msabi extern typeof(Sleep) *const __imp_Sleep;
/** /**
* Opens file on the New Technology. * Opens file on the New Technology.
@ -36,9 +42,16 @@ textwindows int64_t CreateFile(
int dwCreationDisposition, uint32_t dwFlagsAndAttributes, int dwCreationDisposition, uint32_t dwFlagsAndAttributes,
int64_t opt_hTemplateFile) { int64_t opt_hTemplateFile) {
int64_t hHandle; int64_t hHandle;
uint32_t micros = 1;
TryAgain:
hHandle = __imp_CreateFileW(lpFileName, dwDesiredAccess, dwShareMode, hHandle = __imp_CreateFileW(lpFileName, dwDesiredAccess, dwShareMode,
opt_lpSecurityAttributes, dwCreationDisposition, opt_lpSecurityAttributes, dwCreationDisposition,
dwFlagsAndAttributes, opt_hTemplateFile); dwFlagsAndAttributes, opt_hTemplateFile);
if (hHandle == -1 && __imp_GetLastError() == kNtErrorPipeBusy) {
if (micros >= 1024) __imp_Sleep(micros / 1024);
if (micros / 1024 < __SIG_POLLING_INTERVAL_MS) micros <<= 1;
goto TryAgain;
}
if (hHandle == -1) __winerr(); if (hHandle == -1) __winerr();
NTTRACE("CreateFile(%#hs, %s, %s, %s, %s, %s, %ld) → %ld% m", lpFileName, NTTRACE("CreateFile(%#hs, %s, %s, %s, %s, %s, %ld) → %ld% m", lpFileName,
DescribeNtFileAccessFlags(dwDesiredAccess), DescribeNtFileAccessFlags(dwDesiredAccess),

View file

@ -16,14 +16,20 @@
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/calls/sig.internal.h"
#include "libc/calls/syscall_support-nt.internal.h" #include "libc/calls/syscall_support-nt.internal.h"
#include "libc/intrin/describeflags.internal.h" #include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/strace.internal.h" #include "libc/intrin/strace.internal.h"
#include "libc/nt/errors.h"
#include "libc/nt/ipc.h" #include "libc/nt/ipc.h"
#include "libc/nt/runtime.h"
#include "libc/nt/struct/securityattributes.h" #include "libc/nt/struct/securityattributes.h"
#include "libc/nt/synchronization.h"
#include "libc/nt/thunk/msabi.h" #include "libc/nt/thunk/msabi.h"
__msabi extern typeof(CreateNamedPipe) *const __imp_CreateNamedPipeW; __msabi extern typeof(CreateNamedPipe) *const __imp_CreateNamedPipeW;
__msabi extern typeof(GetLastError) *const __imp_GetLastError;
__msabi extern typeof(Sleep) *const __imp_Sleep;
/** /**
* Creates pipe. * Creates pipe.
@ -37,9 +43,16 @@ textwindows int64_t CreateNamedPipe(
uint32_t nDefaultTimeOutMs, uint32_t nDefaultTimeOutMs,
const struct NtSecurityAttributes *opt_lpSecurityAttributes) { const struct NtSecurityAttributes *opt_lpSecurityAttributes) {
int64_t hServer; int64_t hServer;
uint32_t micros = 1;
TryAgain:
hServer = __imp_CreateNamedPipeW(lpName, dwOpenMode, dwPipeMode, hServer = __imp_CreateNamedPipeW(lpName, dwOpenMode, dwPipeMode,
nMaxInstances, nOutBufferSize, nInBufferSize, nMaxInstances, nOutBufferSize, nInBufferSize,
nDefaultTimeOutMs, opt_lpSecurityAttributes); nDefaultTimeOutMs, opt_lpSecurityAttributes);
if (hServer == -1 && __imp_GetLastError() == kNtErrorPipeBusy) {
if (micros >= 1024) __imp_Sleep(micros / 1024);
if (micros / 1024 < __SIG_POLLING_INTERVAL_MS) micros <<= 1;
goto TryAgain;
}
if (hServer == -1) __winerr(); if (hServer == -1) __winerr();
NTTRACE("CreateNamedPipe(%#hs, %s, %s, %u, %'u, %'u, %'u, %s) → %ld% m", NTTRACE("CreateNamedPipe(%#hs, %s, %s, %u, %'u, %'u, %'u, %s) → %ld% m",
lpName, DescribeNtPipeOpenFlags(dwOpenMode), lpName, DescribeNtPipeOpenFlags(dwOpenMode),

View file

@ -131,10 +131,14 @@ textstartup void cosmo(long *sp, struct Syslib *m1) {
__mmi_lock_obj._type = PTHREAD_MUTEX_RECURSIVE; __mmi_lock_obj._type = PTHREAD_MUTEX_RECURSIVE;
// record system provided stack to memory manager // record system provided stack to memory manager
// todo: how do we get the real size of the stack
// if `y` is too small mmap will destroy it
// if `x` is too high, backtraces will fail
uintptr_t t = (uintptr_t)__builtin_frame_address(0);
uintptr_t s = (uintptr_t)sp; uintptr_t s = (uintptr_t)sp;
uintptr_t z = GetStackSize() << 1; uintptr_t z = GetStackSize() << 1;
_mmi.i = 1; _mmi.i = 1;
_mmi.p->x = (s & -z) >> 16; _mmi.p->x = MIN((s & -z) >> 16, (t & -z) >> 16);
_mmi.p->y = MIN(((s & -z) + (z - 1)) >> 16, INT_MAX); _mmi.p->y = MIN(((s & -z) + (z - 1)) >> 16, INT_MAX);
_mmi.p->size = z; _mmi.p->size = z;
_mmi.p->prot = PROT_READ | PROT_WRITE; _mmi.p->prot = PROT_READ | PROT_WRITE;

View file

@ -48,12 +48,14 @@
#include "libc/nt/runtime.h" #include "libc/nt/runtime.h"
#include "libc/nt/signals.h" #include "libc/nt/signals.h"
#include "libc/nt/struct/ntexceptionpointers.h" #include "libc/nt/struct/ntexceptionpointers.h"
#include "libc/nt/synchronization.h"
#include "libc/runtime/internal.h" #include "libc/runtime/internal.h"
#include "libc/runtime/memtrack.internal.h" #include "libc/runtime/memtrack.internal.h"
#include "libc/runtime/runtime.h" #include "libc/runtime/runtime.h"
#include "libc/runtime/symbols.internal.h" #include "libc/runtime/symbols.internal.h"
#include "libc/sock/internal.h" #include "libc/sock/internal.h"
#include "libc/str/str.h" #include "libc/str/str.h"
#include "libc/sysv/consts/limits.h"
#include "libc/sysv/consts/map.h" #include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/o.h" #include "libc/sysv/consts/o.h"
#include "libc/sysv/consts/prot.h" #include "libc/sysv/consts/prot.h"
@ -108,20 +110,36 @@ static dontinline textwindows bool ForkIo2(int64_t h, void *buf, size_t n,
static dontinline textwindows bool WriteAll(int64_t h, void *buf, size_t n) { static dontinline textwindows bool WriteAll(int64_t h, void *buf, size_t n) {
bool ok; bool ok;
// kprintf("WriteAll(%ld, %p, %zu);\n", h, buf, n);
ok = ForkIo2(h, buf, n, WriteFile, "WriteFile", false); ok = ForkIo2(h, buf, n, WriteFile, "WriteFile", false);
#ifndef NDEBUG
if (ok) ok = ForkIo2(h, &n, sizeof(n), WriteFile, "WriteFile", false);
#endif
#ifdef SYSDEBUG #ifdef SYSDEBUG
if (!ok) { if (!ok) {
kprintf("failed to write %zu bytes to forked child: %d\n", n, kprintf("failed to write %zu bytes to forked child: %d\n", n,
GetLastError()); GetLastError());
} }
#endif #endif
// Sleep(10);
return ok; return ok;
} }
static textwindows dontinline void ReadOrDie(int64_t h, void *buf, size_t n) { static textwindows dontinline void ReadOrDie(int64_t h, void *buf, size_t n) {
// kprintf("ReadOrDie(%ld, %p, %zu);\n", h, buf, n);
if (!ForkIo2(h, buf, n, ReadFile, "ReadFile", true)) { if (!ForkIo2(h, buf, n, ReadFile, "ReadFile", true)) {
AbortFork("ReadFile"); AbortFork("ReadFile1");
} }
#ifndef NDEBUG
size_t got;
if (!ForkIo2(h, &got, sizeof(got), ReadFile, "ReadFile", true)) {
AbortFork("ReadFile2");
}
if (got != n) {
AbortFork("ReadFile_SIZE_CHECK");
}
#endif
// Sleep(10);
} }
static textwindows int64_t MapOrDie(uint32_t prot, uint64_t size) { static textwindows int64_t MapOrDie(uint32_t prot, uint64_t size) {
@ -276,6 +294,7 @@ textwindows void WinMainForked(void) {
textwindows int sys_fork_nt(uint32_t dwCreationFlags) { textwindows int sys_fork_nt(uint32_t dwCreationFlags) {
jmp_buf jb; jmp_buf jb;
uint32_t op;
uint32_t oldprot; uint32_t oldprot;
char ok, threaded; char ok, threaded;
char **args, **args2; char **args, **args2;
@ -290,12 +309,10 @@ textwindows int sys_fork_nt(uint32_t dwCreationFlags) {
tib = __tls_enabled ? __get_tls() : 0; tib = __tls_enabled ? __get_tls() : 0;
if (!setjmp(jb)) { if (!setjmp(jb)) {
pid = untrackpid = __reservefd_unlocked(-1); pid = untrackpid = __reservefd_unlocked(-1);
reader = CreateNamedPipe(CreatePipeName(pipename), reader = CreateNamedPipe(CreatePipeName(pipename), kNtPipeAccessInbound,
kNtPipeAccessInbound | kNtFileFlagOverlapped, kNtPipeTypeByte | kNtPipeReadmodeByte, 1, PIPE_BUF,
kNtPipeTypeMessage | kNtPipeReadmodeMessage, 1, PIPE_BUF, 0, &kNtIsInheritable);
65536, 65536, 0, &kNtIsInheritable); writer = CreateFile(pipename, kNtGenericWrite, 0, 0, kNtOpenExisting, 0, 0);
writer = CreateFile(pipename, kNtGenericWrite, 0, 0, kNtOpenExisting,
kNtFileFlagOverlapped, 0);
if (pid != -1 && reader != -1 && writer != -1) { if (pid != -1 && reader != -1 && writer != -1) {
p = stpcpy(forkvar, "_FORK="); p = stpcpy(forkvar, "_FORK=");
p = FormatUint64(p, reader); p = FormatUint64(p, reader);
@ -331,7 +348,6 @@ textwindows int sys_fork_nt(uint32_t dwCreationFlags) {
} }
for (i = 0; i < _mmi.i && ok; ++i) { for (i = 0; i < _mmi.i && ok; ++i) {
if ((_mmi.p[i].flags & MAP_TYPE) != MAP_SHARED) { if ((_mmi.p[i].flags & MAP_TYPE) != MAP_SHARED) {
uint32_t op;
char *p = (char *)((uint64_t)_mmi.p[i].x << 16); char *p = (char *)((uint64_t)_mmi.p[i].x << 16);
// XXX: forking destroys thread guard pages currently // XXX: forking destroys thread guard pages currently
VirtualProtect( VirtualProtect(

View file

@ -464,6 +464,8 @@ dontasan textstartup void __printargs(const char *prologue) {
PRINT(" - stderr"); PRINT(" - stderr");
} }
kprintf(prologue); kprintf(prologue);
errno = 0;
kprintf(" isatty = %d% m\n", isatty(i));
if (!tcgetwinsize(i, &ws)) { if (!tcgetwinsize(i, &ws)) {
kprintf(" ws_row = %d\n", ws.ws_row); kprintf(" ws_row = %d\n", ws.ws_row);
kprintf(" ws_col = %d\n", ws.ws_col); kprintf(" ws_col = %d\n", ws.ws_col);

View file

@ -18,10 +18,13 @@
*/ */
#include "libc/assert.h" #include "libc/assert.h"
#include "libc/calls/struct/fd.internal.h" #include "libc/calls/struct/fd.internal.h"
#include "libc/nt/thunk/msabi.h"
#include "libc/nt/winsock.h" #include "libc/nt/winsock.h"
#include "libc/sock/internal.h" #include "libc/sock/internal.h"
#include "libc/sock/syscall_fd.internal.h" #include "libc/sock/syscall_fd.internal.h"
__msabi extern typeof(__sys_bind_nt) *const __imp_bind;
textwindows int sys_bind_nt(struct Fd *fd, const void *addr, textwindows int sys_bind_nt(struct Fd *fd, const void *addr,
uint32_t addrsize) { uint32_t addrsize) {
unassert(fd->kind == kFdSocket); unassert(fd->kind == kFdSocket);

View file

@ -16,11 +16,14 @@
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/log/backtrace.internal.h"
#include "libc/mem/mem.h" #include "libc/mem/mem.h"
#include "libc/nt/thunk/msabi.h"
#include "libc/nt/winsock.h"
#include "libc/sock/internal.h" #include "libc/sock/internal.h"
#include "libc/sock/syscall_fd.internal.h" #include "libc/sock/syscall_fd.internal.h"
__msabi extern typeof(__sys_closesocket_nt) *const __imp_closesocket;
/** /**
* Closes socket on Windows. * Closes socket on Windows.
* *
@ -30,7 +33,7 @@ textwindows int sys_closesocket_nt(struct Fd *fd) {
struct SockFd *sockfd; struct SockFd *sockfd;
sockfd = (struct SockFd *)fd->extra; sockfd = (struct SockFd *)fd->extra;
free(sockfd); free(sockfd);
int rc = __sys_closesocket_nt(fd->handle); int rc = __imp_closesocket(fd->handle);
if (rc != -1) { if (rc != -1) {
return 0; return 0;
} else { } else {

View file

@ -19,13 +19,12 @@
#include "libc/mem/mem.h" #include "libc/mem/mem.h"
#include "libc/nt/winsock.h" #include "libc/nt/winsock.h"
#include "libc/sock/internal.h" #include "libc/sock/internal.h"
#include "libc/str/str.h"
textwindows struct SockFd *_dupsockfd(struct SockFd *sockfd) { textwindows struct SockFd *_dupsockfd(struct SockFd *sockfd) {
struct SockFd *newsf; struct SockFd *newsf;
if ((newsf = calloc(1, sizeof(struct SockFd)))) { if ((newsf = malloc(sizeof(struct SockFd)))) {
newsf->family = sockfd->family; memcpy(newsf, sockfd, sizeof(*sockfd));
newsf->type = sockfd->type;
newsf->protocol = sockfd->protocol;
} }
return newsf; return newsf;
} }

View file

@ -19,6 +19,7 @@
#include "libc/assert.h" #include "libc/assert.h"
#include "libc/calls/struct/timeval.h" #include "libc/calls/struct/timeval.h"
#include "libc/nt/struct/linger.h" #include "libc/nt/struct/linger.h"
#include "libc/nt/thunk/msabi.h"
#include "libc/nt/winsock.h" #include "libc/nt/winsock.h"
#include "libc/sock/internal.h" #include "libc/sock/internal.h"
#include "libc/sock/sock.h" #include "libc/sock/sock.h"
@ -29,6 +30,8 @@
#include "libc/sysv/consts/sol.h" #include "libc/sysv/consts/sol.h"
#include "libc/sysv/errfuns.h" #include "libc/sysv/errfuns.h"
__msabi extern typeof(__sys_getsockopt_nt) *const __imp_getsockopt;
textwindows int sys_getsockopt_nt(struct Fd *fd, int level, int optname, textwindows int sys_getsockopt_nt(struct Fd *fd, int level, int optname,
void *out_opt_optval, void *out_opt_optval,
uint32_t *inout_optlen) { uint32_t *inout_optlen) {
@ -63,8 +66,8 @@ textwindows int sys_getsockopt_nt(struct Fd *fd, int level, int optname,
} }
// TODO(jart): Use WSAIoctl? // TODO(jart): Use WSAIoctl?
if (__sys_getsockopt_nt(fd->handle, level, optname, out_opt_optval, if (__imp_getsockopt(fd->handle, level, optname, out_opt_optval,
inout_optlen) == -1) { inout_optlen) == -1) {
return __winsockerr(); return __winsockerr();
} }

View file

@ -80,7 +80,7 @@ int sys_select_nt(int, fd_set *, fd_set *, fd_set *, struct timeval *,
size_t __iovec2nt(struct NtIovec[hasatleast 16], const struct iovec *, size_t); size_t __iovec2nt(struct NtIovec[hasatleast 16], const struct iovec *, size_t);
void WinSockInit(void); void WinSockInit(void);
int64_t __winsockerr(void) nocallback; int64_t __winsockerr(void);
int __fixupnewsockfd(int, int); int __fixupnewsockfd(int, int);
int64_t __winsockblock(int64_t, unsigned, int64_t, uint32_t); int64_t __winsockblock(int64_t, unsigned, int64_t, uint32_t);
struct SockFd *_dupsockfd(struct SockFd *); struct SockFd *_dupsockfd(struct SockFd *);

View file

@ -17,13 +17,16 @@
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/assert.h" #include "libc/assert.h"
#include "libc/nt/thunk/msabi.h"
#include "libc/nt/winsock.h" #include "libc/nt/winsock.h"
#include "libc/sock/internal.h" #include "libc/sock/internal.h"
#include "libc/sock/syscall_fd.internal.h" #include "libc/sock/syscall_fd.internal.h"
__msabi extern typeof(__sys_listen_nt) *const __imp_listen;
textwindows int sys_listen_nt(struct Fd *fd, int backlog) { textwindows int sys_listen_nt(struct Fd *fd, int backlog) {
npassert(fd->kind == kFdSocket); npassert(fd->kind == kFdSocket);
if (__sys_listen_nt(fd->handle, backlog) != -1) { if (__imp_listen(fd->handle, backlog) != -1) {
return 0; return 0;
} else { } else {
return __winsockerr(); return __winsockerr();

View file

@ -34,12 +34,15 @@
/** /**
* Receives data from network. * Receives data from network.
* *
* This function blocks unless MSG_DONTWAIT is passed.
*
* @param fd is the file descriptor returned by socket() * @param fd is the file descriptor returned by socket()
* @param buf is where received network data gets copied * @param buf is where received network data gets copied
* @param size is the byte capacity of buf * @param size is the byte capacity of buf
* @param flags can have MSG_{WAITALL,DONTROUTE,PEEK,OOB}, etc. * @param flags is a bitmask which may contain any of the following:
* - `MSG_DONTWAIT` to force `O_NONBLOCK` behavior for this call
* - `MSG_OOB` is broadly supported (untested by cosmo)
* - `MSG_PEEK` is broadly supported (untested by cosmo)
* - `MSG_WAITALL` is broadly supported (untested by cosmo)
* - `MSG_DONTROUTE` is broadly supported (untested by cosmo)
* @param opt_out_srcaddr receives the binary ip:port of the data's origin * @param opt_out_srcaddr receives the binary ip:port of the data's origin
* @param opt_inout_srcaddrsize is srcaddr capacity which gets updated * @param opt_inout_srcaddrsize is srcaddr capacity which gets updated
* @return number of bytes received, 0 on remote close, or -1 w/ errno * @return number of bytes received, 0 on remote close, or -1 w/ errno

View file

@ -20,6 +20,7 @@
#include "libc/limits.h" #include "libc/limits.h"
#include "libc/macros.internal.h" #include "libc/macros.internal.h"
#include "libc/nt/struct/linger.h" #include "libc/nt/struct/linger.h"
#include "libc/nt/thunk/msabi.h"
#include "libc/sock/internal.h" #include "libc/sock/internal.h"
#include "libc/sock/struct/linger.h" #include "libc/sock/struct/linger.h"
#include "libc/sock/syscall_fd.internal.h" #include "libc/sock/syscall_fd.internal.h"
@ -28,6 +29,8 @@
#include "libc/sysv/consts/sol.h" #include "libc/sysv/consts/sol.h"
#include "libc/sysv/errfuns.h" #include "libc/sysv/errfuns.h"
__msabi extern typeof(__sys_setsockopt_nt) *const __imp_setsockopt;
textwindows int sys_setsockopt_nt(struct Fd *fd, int level, int optname, textwindows int sys_setsockopt_nt(struct Fd *fd, int level, int optname,
const void *optval, uint32_t optlen) { const void *optval, uint32_t optlen) {
int64_t ms, micros; int64_t ms, micros;
@ -70,7 +73,7 @@ textwindows int sys_setsockopt_nt(struct Fd *fd, int level, int optname,
} }
} }
if (__sys_setsockopt_nt(fd->handle, level, optname, optval, optlen) != -1) { if (__imp_setsockopt(fd->handle, level, optname, optval, optlen) != -1) {
return 0; return 0;
} else { } else {
return __winsockerr(); return __winsockerr();

View file

@ -40,10 +40,10 @@ static bool setsockopt_polyfill(int *optname) {
/** /**
* Modifies socket settings. * Modifies socket settings.
* *
* This function is the ultimate rabbit hole. Basic usage: * Basic usage:
* *
* int yes = 1; * int yes = 1;
* setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &yes, sizeof(yes)); * setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
* *
* @param level can be SOL_SOCKET, SOL_IP, SOL_TCP, etc. * @param level can be SOL_SOCKET, SOL_IP, SOL_TCP, etc.
* @param optname can be SO_{REUSE{PORT,ADDR},KEEPALIVE,etc.} etc. * @param optname can be SO_{REUSE{PORT,ADDR},KEEPALIVE,etc.} etc.

View file

@ -16,12 +16,15 @@
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/nt/thunk/msabi.h"
#include "libc/nt/winsock.h" #include "libc/nt/winsock.h"
#include "libc/sock/internal.h" #include "libc/sock/internal.h"
#include "libc/sock/syscall_fd.internal.h" #include "libc/sock/syscall_fd.internal.h"
__msabi extern typeof(__sys_shutdown_nt) *const __imp_shutdown;
textwindows int sys_shutdown_nt(struct Fd *fd, int how) { textwindows int sys_shutdown_nt(struct Fd *fd, int how) {
if (__sys_shutdown_nt(fd->handle, how) != -1) { if (__imp_shutdown(fd->handle, how) != -1) {
return 0; return 0;
} else { } else {
return __winsockerr(); return __winsockerr();

View file

@ -116,8 +116,9 @@ void OnInterrupt(int sig) {
} }
void OnChildTerminated(int sig) { void OnChildTerminated(int sig) {
int ws, pid; int e, ws, pid;
sigset_t ss, oldss; sigset_t ss, oldss;
e = errno; // SIGCHLD can be called asynchronously
sigfillset(&ss); sigfillset(&ss);
sigdelset(&ss, SIGTERM); sigdelset(&ss, SIGTERM);
sigprocmask(SIG_BLOCK, &ss, &oldss); sigprocmask(SIG_BLOCK, &ss, &oldss);
@ -140,6 +141,7 @@ void OnChildTerminated(int sig) {
} }
} }
sigprocmask(SIG_SETMASK, &oldss, 0); sigprocmask(SIG_SETMASK, &oldss, 0);
errno = e;
} }
wontreturn void ShowUsage(FILE *f, int rc) { wontreturn void ShowUsage(FILE *f, int rc) {