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"
textwindows int _check_interrupts(bool restartable, struct Fd *fd) {
int rc;
int e, rc;
e = errno;
if (_weaken(pthread_testcancel_np) &&
(rc = _weaken(pthread_testcancel_np)())) {
errno = rc;
return -1;
}
if (_weaken(_check_sigalrm)) _weaken(_check_sigalrm)();
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(_check_sigalrm)) {
_weaken(_check_sigalrm)();
}
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;
}

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
* 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
* @see xsigaction() for a much better api
* @asyncsignalsafe

View file

@ -17,12 +17,18 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/nt/createfile.h"
#include "libc/calls/sig.internal.h"
#include "libc/calls/syscall_support-nt.internal.h"
#include "libc/intrin/describeflags.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"
__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.
@ -36,9 +42,16 @@ textwindows int64_t CreateFile(
int dwCreationDisposition, uint32_t dwFlagsAndAttributes,
int64_t opt_hTemplateFile) {
int64_t hHandle;
uint32_t micros = 1;
TryAgain:
hHandle = __imp_CreateFileW(lpFileName, dwDesiredAccess, dwShareMode,
opt_lpSecurityAttributes, dwCreationDisposition,
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();
NTTRACE("CreateFile(%#hs, %s, %s, %s, %s, %s, %ld) → %ld% m", lpFileName,
DescribeNtFileAccessFlags(dwDesiredAccess),

View file

@ -16,14 +16,20 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/sig.internal.h"
#include "libc/calls/syscall_support-nt.internal.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/strace.internal.h"
#include "libc/nt/errors.h"
#include "libc/nt/ipc.h"
#include "libc/nt/runtime.h"
#include "libc/nt/struct/securityattributes.h"
#include "libc/nt/synchronization.h"
#include "libc/nt/thunk/msabi.h"
__msabi extern typeof(CreateNamedPipe) *const __imp_CreateNamedPipeW;
__msabi extern typeof(GetLastError) *const __imp_GetLastError;
__msabi extern typeof(Sleep) *const __imp_Sleep;
/**
* Creates pipe.
@ -37,9 +43,16 @@ textwindows int64_t CreateNamedPipe(
uint32_t nDefaultTimeOutMs,
const struct NtSecurityAttributes *opt_lpSecurityAttributes) {
int64_t hServer;
uint32_t micros = 1;
TryAgain:
hServer = __imp_CreateNamedPipeW(lpName, dwOpenMode, dwPipeMode,
nMaxInstances, nOutBufferSize, nInBufferSize,
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();
NTTRACE("CreateNamedPipe(%#hs, %s, %s, %u, %'u, %'u, %'u, %s) → %ld% m",
lpName, DescribeNtPipeOpenFlags(dwOpenMode),

View file

@ -131,10 +131,14 @@ textstartup void cosmo(long *sp, struct Syslib *m1) {
__mmi_lock_obj._type = PTHREAD_MUTEX_RECURSIVE;
// 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 z = GetStackSize() << 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->size = z;
_mmi.p->prot = PROT_READ | PROT_WRITE;

View file

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

View file

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

View file

@ -18,10 +18,13 @@
*/
#include "libc/assert.h"
#include "libc/calls/struct/fd.internal.h"
#include "libc/nt/thunk/msabi.h"
#include "libc/nt/winsock.h"
#include "libc/sock/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,
uint32_t addrsize) {
unassert(fd->kind == kFdSocket);

View file

@ -16,11 +16,14 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/log/backtrace.internal.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/syscall_fd.internal.h"
__msabi extern typeof(__sys_closesocket_nt) *const __imp_closesocket;
/**
* Closes socket on Windows.
*
@ -30,7 +33,7 @@ textwindows int sys_closesocket_nt(struct Fd *fd) {
struct SockFd *sockfd;
sockfd = (struct SockFd *)fd->extra;
free(sockfd);
int rc = __sys_closesocket_nt(fd->handle);
int rc = __imp_closesocket(fd->handle);
if (rc != -1) {
return 0;
} else {

View file

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

View file

@ -19,6 +19,7 @@
#include "libc/assert.h"
#include "libc/calls/struct/timeval.h"
#include "libc/nt/struct/linger.h"
#include "libc/nt/thunk/msabi.h"
#include "libc/nt/winsock.h"
#include "libc/sock/internal.h"
#include "libc/sock/sock.h"
@ -29,6 +30,8 @@
#include "libc/sysv/consts/sol.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,
void *out_opt_optval,
uint32_t *inout_optlen) {
@ -63,8 +66,8 @@ textwindows int sys_getsockopt_nt(struct Fd *fd, int level, int optname,
}
// TODO(jart): Use WSAIoctl?
if (__sys_getsockopt_nt(fd->handle, level, optname, out_opt_optval,
inout_optlen) == -1) {
if (__imp_getsockopt(fd->handle, level, optname, out_opt_optval,
inout_optlen) == -1) {
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);
void WinSockInit(void);
int64_t __winsockerr(void) nocallback;
int64_t __winsockerr(void);
int __fixupnewsockfd(int, int);
int64_t __winsockblock(int64_t, unsigned, int64_t, uint32_t);
struct SockFd *_dupsockfd(struct SockFd *);

View file

@ -17,13 +17,16 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/assert.h"
#include "libc/nt/thunk/msabi.h"
#include "libc/nt/winsock.h"
#include "libc/sock/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) {
npassert(fd->kind == kFdSocket);
if (__sys_listen_nt(fd->handle, backlog) != -1) {
if (__imp_listen(fd->handle, backlog) != -1) {
return 0;
} else {
return __winsockerr();

View file

@ -34,12 +34,15 @@
/**
* Receives data from network.
*
* This function blocks unless MSG_DONTWAIT is passed.
*
* @param fd is the file descriptor returned by socket()
* @param buf is where received network data gets copied
* @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_inout_srcaddrsize is srcaddr capacity which gets updated
* @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/macros.internal.h"
#include "libc/nt/struct/linger.h"
#include "libc/nt/thunk/msabi.h"
#include "libc/sock/internal.h"
#include "libc/sock/struct/linger.h"
#include "libc/sock/syscall_fd.internal.h"
@ -28,6 +29,8 @@
#include "libc/sysv/consts/sol.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,
const void *optval, uint32_t optlen) {
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;
} else {
return __winsockerr();

View file

@ -40,10 +40,10 @@ static bool setsockopt_polyfill(int *optname) {
/**
* Modifies socket settings.
*
* This function is the ultimate rabbit hole. Basic usage:
* Basic usage:
*
* int yes = 1;
* setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &yes, sizeof(yes));
* int yes = 1;
* setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
*
* @param level can be SOL_SOCKET, SOL_IP, SOL_TCP, 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
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/nt/thunk/msabi.h"
#include "libc/nt/winsock.h"
#include "libc/sock/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) {
if (__sys_shutdown_nt(fd->handle, how) != -1) {
if (__imp_shutdown(fd->handle, how) != -1) {
return 0;
} else {
return __winsockerr();

View file

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