mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-06-30 00:08:30 +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
|
@ -558,34 +558,6 @@ static int ioctl_siocgifflags(int fd, void *arg) {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets "close on exec" on file descriptor the fast way.
|
||||
*
|
||||
* @see ioctl(fd, FIOCLEX, 0) dispatches here
|
||||
*/
|
||||
static int ioctl_fioclex(int fd, int req) {
|
||||
int rc;
|
||||
if (fd >= 0) {
|
||||
if (IsWindows() || (fd < g_fds.n && g_fds.p[fd].kind == kFdZip)) {
|
||||
if (__isfdopen(fd)) {
|
||||
if (req == FIOCLEX) {
|
||||
g_fds.p[fd].flags |= O_CLOEXEC;
|
||||
} else {
|
||||
g_fds.p[fd].flags &= ~O_CLOEXEC;
|
||||
}
|
||||
rc = 0;
|
||||
} else {
|
||||
rc = ebadf();
|
||||
}
|
||||
} else {
|
||||
rc = sys_ioctl(fd, req);
|
||||
}
|
||||
} else {
|
||||
rc = einval();
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs special i/o operation on file descriptor.
|
||||
*
|
||||
|
@ -618,17 +590,6 @@ static int ioctl_fioclex(int fd, int req) {
|
|||
* - `TIOCNXCL` to give up exclusive mode on terminal. Only
|
||||
* available on UNIX.
|
||||
*
|
||||
* - `FIOCLEX` sets the `O_CLOEXEC` state (no arg) noting that this
|
||||
* polyfill may be removed in the future, and code should migrate
|
||||
* to the equivalent fcntl() api.
|
||||
*
|
||||
* - `FIONBIO` sets the `O_NONBLOCK` state (arg is `int *enabled`)
|
||||
* which is supported on Windows for sockets.
|
||||
*
|
||||
* - `FIONCLEX` clears the `O_CLOEXEC` state (no arg) noting that
|
||||
* this polyfill may be removed in the future, and code should
|
||||
* migrate to the equivalent fcntl() api.
|
||||
*
|
||||
* - `SIOCGIFCONF` takes an struct ifconf object of a given size,
|
||||
* whose arg is `struct ifconf *`. It implements the Linux style
|
||||
* and modifies the following:
|
||||
|
@ -647,6 +608,9 @@ static int ioctl_fioclex(int fd, int req) {
|
|||
* network broadcast addr. This data structure should be obtained
|
||||
* by calling `SIOCGIFCONF`.
|
||||
*
|
||||
* - `FIONBIO` isn't polyfilled; use `fcntl(F_SETFL, O_NONBLOCK)`
|
||||
* - `FIOCLEX` isn't polyfilled; use `fcntl(F_SETFD, FD_CLOEXEC)`
|
||||
* - `FIONCLEX` isn't polyfilled; use `fcntl(F_SETFD, 0)`
|
||||
* - `TCGETS` isn't polyfilled; use tcgetattr()
|
||||
* - `TCSETS` isn't polyfilled; use tcsetattr()
|
||||
* - `TCSETSW` isn't polyfilled; use tcsetattr()
|
||||
|
@ -673,10 +637,6 @@ int ioctl(int fd, unsigned long request, ...) {
|
|||
va_end(va);
|
||||
if (request == FIONBIO) {
|
||||
rc = ioctl_default(fd, request, arg);
|
||||
} else if (request == FIOCLEX) {
|
||||
rc = ioctl_fioclex(fd, request);
|
||||
} else if (request == FIONCLEX) {
|
||||
rc = ioctl_fioclex(fd, request);
|
||||
} else if (request == TIOCGWINSZ) {
|
||||
rc = tcgetwinsize(fd, arg);
|
||||
} else if (request == TIOCSWINSZ) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue