mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-11 21:49:12 +00:00
Support non-blocking i/o across platforms
This change introduces new tests for `O_NONBLOCK` and `SOCK_NONBLOCK` to confirm that non-blocking i/o is now working on all supported platforms, including Windows. For example, you can now say on Windows, MacOS, etc.: socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, IPPROTO_TCP); To create a non-blocking IPv4 TCP socket. Or you can enable non-blocking i/o on an existing socket / pipe / etc. file descriptor by calling fcntl fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK); This functionality is polyfilled on older Linux kernels too, e.g. RHEL5. Now that fcntl() support is much better the FIOCLEX / FIONCLEX polyfills for ioctl() have been removed since they're ugly non-POSIX diameond APIs This change fixes a weakness in kprintf() that was causing Windows trace tools to frequently crash.
This commit is contained in:
parent
5c9e03e3e0
commit
1d4eb08fa1
102 changed files with 678 additions and 331 deletions
38
libc/intrin/cancelioex.c
Normal file
38
libc/intrin/cancelioex.c
Normal file
|
@ -0,0 +1,38 @@
|
|||
/*-*- 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 2023 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/syscall_support-nt.internal.h"
|
||||
#include "libc/intrin/describentoverlapped.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/nt/struct/overlapped.h"
|
||||
#include "libc/nt/thread.h"
|
||||
#include "libc/nt/thunk/msabi.h"
|
||||
|
||||
__msabi extern typeof(CancelIoEx) *const __imp_CancelIoEx;
|
||||
|
||||
/**
|
||||
* Cancels Windows i/o operation.
|
||||
*/
|
||||
bool32 CancelIoEx(int64_t hFile, struct NtOverlapped *opt_lpOverlapped) {
|
||||
bool32 ok;
|
||||
ok = __imp_CancelIoEx(hFile, opt_lpOverlapped);
|
||||
if (!ok) __winerr();
|
||||
NTTRACE("CancelIoEx(%ld, %s) → %hhhd% m", hFile,
|
||||
DescribeNtOverlapped(opt_lpOverlapped), ok);
|
||||
return ok;
|
||||
}
|
|
@ -146,6 +146,7 @@ o/$(MODE)/libc/intrin/exit1.greg.o \
|
|||
o/$(MODE)/libc/intrin/wsarecv.o \
|
||||
o/$(MODE)/libc/intrin/wsarecvfrom.o \
|
||||
o/$(MODE)/libc/intrin/createfile.o \
|
||||
o/$(MODE)/libc/intrin/cancelioex.o \
|
||||
o/$(MODE)/libc/intrin/reopenfile.o \
|
||||
o/$(MODE)/libc/intrin/deletefile.o \
|
||||
o/$(MODE)/libc/intrin/createpipe.o \
|
||||
|
@ -175,6 +176,7 @@ o/$(MODE)/libc/intrin/mapviewoffileexnuma.o \
|
|||
o/$(MODE)/libc/intrin/createfilemapping.o \
|
||||
o/$(MODE)/libc/intrin/createfilemappingnuma.o \
|
||||
o/$(MODE)/libc/intrin/waitformultipleobjects.o \
|
||||
o/$(MODE)/libc/intrin/wsagetoverlappedresult.o \
|
||||
o/$(MODE)/libc/intrin/generateconsolectrlevent.o \
|
||||
o/$(MODE)/libc/intrin/wsawaitformultipleevents.o: private\
|
||||
CFLAGS += \
|
||||
|
|
|
@ -26,12 +26,14 @@
|
|||
#include "libc/errno.h"
|
||||
#include "libc/fmt/divmod10.internal.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/fmt/itoa.h"
|
||||
#include "libc/fmt/magnumstrs.internal.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/asancodes.h"
|
||||
#include "libc/intrin/atomic.h"
|
||||
#include "libc/intrin/bits.h"
|
||||
#include "libc/intrin/cmpxchg.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/intrin/likely.h"
|
||||
#include "libc/intrin/nomultics.internal.h"
|
||||
#include "libc/intrin/safemacros.internal.h"
|
||||
|
@ -259,6 +261,7 @@ privileged static size_t kformat(char *b, size_t n, const char *fmt,
|
|||
va_list va) {
|
||||
int si, y;
|
||||
wint_t t, u;
|
||||
char errnum[12];
|
||||
const char *abet;
|
||||
signed char type;
|
||||
const char *s, *f;
|
||||
|
@ -539,6 +542,10 @@ privileged static size_t kformat(char *b, size_t n, const char *fmt,
|
|||
} else {
|
||||
type = 0;
|
||||
s = _strerrno(e);
|
||||
if (!s) {
|
||||
FormatInt32(errnum, e);
|
||||
s = errnum;
|
||||
}
|
||||
goto FormatString;
|
||||
}
|
||||
}
|
||||
|
@ -612,7 +619,7 @@ privileged static size_t kformat(char *b, size_t n, const char *fmt,
|
|||
if (cols) --cols; // end quote
|
||||
p = kemitquote(p, e, type, hash);
|
||||
}
|
||||
if (sign == ' ' && (!pdot || prec) && *s) {
|
||||
if (sign == ' ' && (!pdot || prec) && s && *s) {
|
||||
if (p < e) *p = ' ';
|
||||
++p;
|
||||
}
|
||||
|
|
29
libc/intrin/winsockerr.c
Normal file
29
libc/intrin/winsockerr.c
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*-*- 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 2020 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/errno.h"
|
||||
#include "libc/nt/winsock.h"
|
||||
#include "libc/sock/internal.h"
|
||||
|
||||
/**
|
||||
* Error return path for winsock wrappers.
|
||||
*/
|
||||
textwindows int64_t __winsockerr(void) {
|
||||
errno = __dos2errno(WSAGetLastError());
|
||||
return -1;
|
||||
}
|
59
libc/intrin/wsagetoverlappedresult.c
Normal file
59
libc/intrin/wsagetoverlappedresult.c
Normal file
|
@ -0,0 +1,59 @@
|
|||
/*-*- 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 2023 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/errno.h"
|
||||
#include "libc/intrin/describentoverlapped.internal.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/mem/alloca.h"
|
||||
#include "libc/nt/thunk/msabi.h"
|
||||
#include "libc/nt/winsock.h"
|
||||
#include "libc/sock/internal.h"
|
||||
|
||||
__msabi extern typeof(WSAGetOverlappedResult)
|
||||
*const __imp_WSAGetOverlappedResult;
|
||||
|
||||
static char *DescribeTransfer(char buf[16], bool32 ok, uint32_t *transfer) {
|
||||
if (ok) {
|
||||
ksnprintf(buf, 16, "%'u", *transfer);
|
||||
return buf;
|
||||
} else {
|
||||
return "n/a";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets overlap i/o result.
|
||||
*
|
||||
* @return true on success, or false on failure
|
||||
* @note this wrapper takes care of ABI, STRACE(), and __winsockerr()
|
||||
*/
|
||||
bool32 WSAGetOverlappedResult(uint64_t s,
|
||||
const struct NtOverlapped *lpOverlapped,
|
||||
uint32_t *out_lpcbTransfer, bool32 fWait,
|
||||
uint32_t *out_lpdwFlags) {
|
||||
bool32 ok;
|
||||
ok = __imp_WSAGetOverlappedResult(s, lpOverlapped, out_lpcbTransfer, fWait,
|
||||
out_lpdwFlags);
|
||||
if (!ok) __winsockerr();
|
||||
NTTRACE("WSAGetOverlappedResult(%ld, %s, [%s], %hhhd, [%#x]) → %hhhd% lm", s,
|
||||
DescribeNtOverlapped(lpOverlapped),
|
||||
DescribeTransfer(alloca(16), ok, out_lpcbTransfer), fWait,
|
||||
*out_lpdwFlags, ok);
|
||||
return ok;
|
||||
}
|
|
@ -16,6 +16,7 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/syscall_support-nt.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/describentoverlapped.internal.h"
|
||||
|
@ -23,6 +24,7 @@
|
|||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/nt/thunk/msabi.h"
|
||||
#include "libc/nt/winsock.h"
|
||||
#include "libc/sock/internal.h"
|
||||
|
||||
__msabi extern typeof(WSARecv) *const __imp_WSARecv;
|
||||
|
||||
|
@ -38,6 +40,12 @@ textwindows int WSARecv(
|
|||
struct NtOverlapped *opt_inout_lpOverlapped,
|
||||
const NtWsaOverlappedCompletionRoutine opt_lpCompletionRoutine) {
|
||||
int rc;
|
||||
if (opt_inout_lpOverlapped) {
|
||||
// Use NULL for this parameter if the lpOverlapped parameter is not
|
||||
// NULL to avoid potentially erroneous results. This parameter can
|
||||
// be NULL only if the lpOverlapped parameter is not NULL.
|
||||
_unassert(!opt_out_lpNumberOfBytesRecvd);
|
||||
}
|
||||
#if defined(SYSDEBUG) && _NTTRACE
|
||||
uint32_t NumberOfBytesRecvd;
|
||||
if (opt_out_lpNumberOfBytesRecvd) {
|
||||
|
@ -50,7 +58,7 @@ textwindows int WSARecv(
|
|||
*opt_out_lpNumberOfBytesRecvd = NumberOfBytesRecvd;
|
||||
}
|
||||
if (rc == -1) {
|
||||
__winerr();
|
||||
__winsockerr();
|
||||
}
|
||||
if (UNLIKELY(__strace > 0) && strace_enabled(0) > 0) {
|
||||
kprintf(STRACE_PROLOGUE "WSARecv(%lu, [", s);
|
||||
|
@ -66,7 +74,7 @@ textwindows int WSARecv(
|
|||
opt_out_lpNumberOfBytesRecvd, inout_lpFlags,
|
||||
opt_inout_lpOverlapped, opt_lpCompletionRoutine);
|
||||
if (rc == -1) {
|
||||
__winerr();
|
||||
__winsockerr();
|
||||
}
|
||||
#endif
|
||||
return rc;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue