mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-03-03 07:29:23 +00:00
Fix flakes in runitd and popen_test
This commit is contained in:
parent
801224df67
commit
2ebc5781a1
18 changed files with 123 additions and 34 deletions
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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),
|
||||||
|
|
|
@ -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),
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 *);
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue