mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-13 14:39:10 +00:00
Make improvements
- Improved async signal safety of read() particularly for longjmp() - Started adding cancel cleanup handlers for locks / etc on Windows - Make /dev/tty work better particularly for uses like `foo | less` - Eagerly read console input into a linked list, so poll can signal - Fix some libc definitional bugs, which configure scripts detected
This commit is contained in:
parent
d6c2830850
commit
0c5dd7b342
85 changed files with 1062 additions and 671 deletions
|
@ -28,6 +28,7 @@
|
|||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sock/select.h"
|
||||
#include "libc/sock/select.internal.h"
|
||||
#include "libc/sysv/consts/nrlinux.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
|
@ -68,6 +69,15 @@ int pselect(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
|
|||
} ss;
|
||||
BEGIN_CANCELLATION_POINT;
|
||||
|
||||
#ifdef SYSDEBUG
|
||||
fd_set old_readfds;
|
||||
fd_set *old_readfds_ptr = 0;
|
||||
fd_set old_writefds;
|
||||
fd_set *old_writefds_ptr = 0;
|
||||
fd_set old_exceptfds;
|
||||
fd_set *old_exceptfds_ptr = 0;
|
||||
#endif
|
||||
|
||||
if (nfds < 0) {
|
||||
rc = einval();
|
||||
} else if (IsAsan() &&
|
||||
|
@ -77,33 +87,55 @@ int pselect(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
|
|||
(timeout && !__asan_is_valid(timeout, sizeof(*timeout))) ||
|
||||
(sigmask && !__asan_is_valid(sigmask, sizeof(*sigmask))))) {
|
||||
rc = efault();
|
||||
} else if (IsLinux()) {
|
||||
if (timeout) {
|
||||
ts = *timeout;
|
||||
tsp = &ts;
|
||||
} else {
|
||||
tsp = 0;
|
||||
}
|
||||
ss.s = sigmask;
|
||||
ss.n = 8;
|
||||
rc = sys_pselect(nfds, readfds, writefds, exceptfds, tsp, &ss);
|
||||
} else if (!IsWindows()) {
|
||||
rc = sys_pselect(nfds, readfds, writefds, exceptfds,
|
||||
(struct timespec *)timeout, sigmask);
|
||||
} else {
|
||||
if (timeout) {
|
||||
tv.tv_sec = timeout->tv_sec;
|
||||
tv.tv_usec = timeout->tv_nsec / 1000;
|
||||
tvp = &tv;
|
||||
} else {
|
||||
tvp = 0;
|
||||
#ifdef SYSDEBUG
|
||||
if (readfds) {
|
||||
old_readfds = *readfds;
|
||||
old_readfds_ptr = &old_readfds;
|
||||
}
|
||||
if (writefds) {
|
||||
old_writefds = *writefds;
|
||||
old_writefds_ptr = &old_writefds;
|
||||
}
|
||||
if (exceptfds) {
|
||||
old_exceptfds = *exceptfds;
|
||||
old_exceptfds_ptr = &old_exceptfds;
|
||||
}
|
||||
#endif
|
||||
if (IsLinux()) {
|
||||
if (timeout) {
|
||||
ts = *timeout;
|
||||
tsp = &ts;
|
||||
} else {
|
||||
tsp = 0;
|
||||
}
|
||||
ss.s = sigmask;
|
||||
ss.n = 8;
|
||||
rc = sys_pselect(nfds, readfds, writefds, exceptfds, tsp, &ss);
|
||||
} else if (!IsWindows()) {
|
||||
rc = sys_pselect(nfds, readfds, writefds, exceptfds,
|
||||
(struct timespec *)timeout, sigmask);
|
||||
} else {
|
||||
if (timeout) {
|
||||
tv.tv_sec = timeout->tv_sec;
|
||||
tv.tv_usec = timeout->tv_nsec / 1000;
|
||||
tvp = &tv;
|
||||
} else {
|
||||
tvp = 0;
|
||||
}
|
||||
rc = sys_select_nt(nfds, readfds, writefds, exceptfds, tvp, sigmask);
|
||||
}
|
||||
rc = sys_select_nt(nfds, readfds, writefds, exceptfds, tvp, sigmask);
|
||||
}
|
||||
|
||||
END_CANCELLATION_POINT;
|
||||
POLLTRACE("pselect(%d, %p, %p, %p, %s, %s) → %d% m", nfds, readfds, writefds,
|
||||
exceptfds, DescribeTimespec(0, timeout), DescribeSigset(0, sigmask),
|
||||
rc);
|
||||
STRACE("pselect(%d, %s → [%s], %s → [%s], %s → [%s], %s, %s) → %d% m", nfds,
|
||||
DescribeFdSet(rc, nfds, old_readfds_ptr),
|
||||
DescribeFdSet(rc, nfds, readfds),
|
||||
DescribeFdSet(rc, nfds, old_writefds_ptr),
|
||||
DescribeFdSet(rc, nfds, writefds),
|
||||
DescribeFdSet(rc, nfds, old_exceptfds_ptr),
|
||||
DescribeFdSet(rc, nfds, exceptfds), //
|
||||
DescribeTimespec(0, timeout), //
|
||||
DescribeSigset(0, sigmask), rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -16,10 +16,12 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/bo.internal.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/state.internal.h"
|
||||
#include "libc/calls/struct/timeval.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/sock/select.h"
|
||||
#include "libc/sock/sock.h"
|
||||
|
@ -34,11 +36,10 @@
|
|||
int sys_select_nt(int nfds, fd_set *readfds, fd_set *writefds,
|
||||
fd_set *exceptfds, struct timeval *timeout,
|
||||
const sigset_t *sigmask) {
|
||||
uint64_t millis;
|
||||
int i, pfds, events, fdcount;
|
||||
struct pollfd fds[64];
|
||||
|
||||
// convert bitsets to pollfd
|
||||
struct pollfd fds[64];
|
||||
for (pfds = i = 0; i < nfds; ++i) {
|
||||
events = 0;
|
||||
if (readfds && FD_ISSET(i, readfds)) events |= POLLIN;
|
||||
|
@ -57,26 +58,49 @@ int sys_select_nt(int nfds, fd_set *readfds, fd_set *writefds,
|
|||
}
|
||||
|
||||
// convert the wait time to a word
|
||||
uint32_t millis;
|
||||
if (!timeout) {
|
||||
millis = -1;
|
||||
} else {
|
||||
millis = timeval_tomillis(*timeout);
|
||||
int64_t ms = timeval_tomillis(*timeout);
|
||||
if (ms < 0 || ms > UINT32_MAX) {
|
||||
millis = -1u;
|
||||
} else {
|
||||
millis = ms;
|
||||
}
|
||||
}
|
||||
|
||||
// call our nt poll implementation
|
||||
BEGIN_BLOCKING_OPERATION;
|
||||
fdcount = sys_poll_nt(fds, pfds, &millis, sigmask);
|
||||
unassert(fdcount < 64);
|
||||
END_BLOCKING_OPERATION;
|
||||
if (fdcount == -1) return -1;
|
||||
if (fdcount < 0) return -1;
|
||||
|
||||
// convert pollfd back to bitsets
|
||||
if (readfds) FD_ZERO(readfds);
|
||||
if (writefds) FD_ZERO(writefds);
|
||||
if (exceptfds) FD_ZERO(exceptfds);
|
||||
for (i = 0; i < fdcount; ++i) {
|
||||
if (fds[i].revents & POLLIN) FD_SET(fds[i].fd, readfds);
|
||||
if (fds[i].revents & POLLOUT) FD_SET(fds[i].fd, writefds);
|
||||
if (fds[i].revents & (POLLERR | POLLNVAL)) FD_SET(fds[i].fd, exceptfds);
|
||||
int bits = 0;
|
||||
for (i = 0; i < pfds; ++i) {
|
||||
if (fds[i].revents & POLLIN) {
|
||||
if (readfds) {
|
||||
FD_SET(fds[i].fd, readfds);
|
||||
++bits;
|
||||
}
|
||||
}
|
||||
if (fds[i].revents & POLLOUT) {
|
||||
if (writefds) {
|
||||
FD_SET(fds[i].fd, writefds);
|
||||
++bits;
|
||||
}
|
||||
}
|
||||
if (fds[i].revents & (POLLERR | POLLNVAL)) {
|
||||
if (exceptfds) {
|
||||
FD_SET(fds[i].fd, exceptfds);
|
||||
++bits;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// store remaining time back in caller's timeval
|
||||
|
@ -84,7 +108,7 @@ int sys_select_nt(int nfds, fd_set *readfds, fd_set *writefds,
|
|||
*timeout = timeval_frommillis(millis);
|
||||
}
|
||||
|
||||
return fdcount;
|
||||
return bits;
|
||||
}
|
||||
|
||||
#endif /* __x86_64__ */
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sock/select.h"
|
||||
#include "libc/sock/select.internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
|
@ -88,7 +90,8 @@ int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
|
|||
}
|
||||
END_CANCELLATION_POINT;
|
||||
|
||||
POLLTRACE("select(%d, %p, %p, %p, [%s]) → %d% m", nfds, readfds, writefds,
|
||||
exceptfds, DescribeTimeval(rc, tvp), rc);
|
||||
STRACE("select(%d, [%s], [%s], [%s], [%s]) → %d% m", nfds,
|
||||
DescribeFdSet(rc, nfds, readfds), DescribeFdSet(rc, nfds, writefds),
|
||||
DescribeFdSet(rc, nfds, exceptfds), DescribeTimeval(rc, tvp), rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
13
libc/sock/select.internal.h
Normal file
13
libc/sock/select.internal.h
Normal file
|
@ -0,0 +1,13 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_SOCK_SELECT_INTERNAL_H_
|
||||
#define COSMOPOLITAN_LIBC_SOCK_SELECT_INTERNAL_H_
|
||||
#include "libc/mem/alloca.h"
|
||||
#include "libc/sock/select.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
const char *DescribeFdSet(char[100], ssize_t, int, fd_set *);
|
||||
#define DescribeFdSet(x, y, z) DescribeFdSet(alloca(100), x, y, z)
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_SOCK_SELECT_INTERNAL_H_ */
|
|
@ -219,3 +219,5 @@ ssize_t sendfile(int outfd, int infd, int64_t *opt_in_out_inoffset,
|
|||
DescribeInOutInt64(rc, opt_in_out_inoffset), uptobytes, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
__weak_reference(sendfile, sendfile64);
|
||||
|
|
|
@ -12,7 +12,7 @@ int32_t __sys_poll(struct pollfd *, uint64_t, signed);
|
|||
int sys_ppoll(struct pollfd *, size_t, const struct timespec *,
|
||||
const sigset_t *, size_t);
|
||||
int sys_poll_metal(struct pollfd *, size_t, unsigned);
|
||||
int sys_poll_nt(struct pollfd *, uint64_t, uint64_t *, const sigset_t *);
|
||||
int sys_poll_nt(struct pollfd *, uint64_t, uint32_t *, const sigset_t *);
|
||||
|
||||
const char *DescribePollFds(char[300], ssize_t, struct pollfd *, size_t);
|
||||
#define DescribePollFds(x, y, z) DescribePollFds(alloca(300), x, y, z)
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "libc/calls/sig.internal.h"
|
||||
#include "libc/calls/struct/timespec.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
#include "libc/nt/enum/wait.h"
|
||||
#include "libc/nt/enum/wsa.h"
|
||||
#include "libc/nt/errors.h"
|
||||
|
@ -113,6 +114,10 @@ BlockingOperation:
|
|||
if (WSAGetOverlappedResult(f->handle, overlapped, &got, nonblock, flags)) {
|
||||
rc = got;
|
||||
} else {
|
||||
if (_weaken(pthread_testcancel_np) &&
|
||||
(err = _weaken(pthread_testcancel_np)())) {
|
||||
return ecanceled();
|
||||
}
|
||||
rc = -1;
|
||||
err = WSAGetLastError();
|
||||
if (err == kNtErrorOperationAborted) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue