Fix some issues with select()

This commit is contained in:
Justine Tunney 2023-10-04 09:10:58 -07:00
parent 6918c3ffc2
commit 982dc4db87
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
4 changed files with 67 additions and 37 deletions

View file

@ -380,9 +380,10 @@ int main(int argc, char *argv[]) {
sigaddset(&block, SIGHUP); sigaddset(&block, SIGHUP);
sigaddset(&block, SIGQUIT); sigaddset(&block, SIGQUIT);
pthread_attr_t attr; pthread_attr_t attr;
int pagesz = getauxval(AT_PAGESZ);
unassert(!pthread_attr_init(&attr)); unassert(!pthread_attr_init(&attr));
unassert(!pthread_attr_setguardsize(&attr, 4096));
unassert(!pthread_attr_setstacksize(&attr, 65536)); unassert(!pthread_attr_setstacksize(&attr, 65536));
unassert(!pthread_attr_setguardsize(&attr, pagesz));
unassert(!pthread_attr_setsigmask_np(&attr, &block)); unassert(!pthread_attr_setsigmask_np(&attr, &block));
pthread_t *th = gc(calloc(threads, sizeof(pthread_t))); pthread_t *th = gc(calloc(threads, sizeof(pthread_t)));
for (i = 0; i < threads; ++i) { for (i = 0; i < threads; ++i) {

View file

@ -43,14 +43,15 @@ const char *(DescribeFdSet)(char buf[N], ssize_t rc, int nfds, fd_set *fds) {
for (int fd = 0; fd < nfds; fd += 64) { for (int fd = 0; fd < nfds; fd += 64) {
uint64_t w = fds->fds_bits[fd >> 6]; uint64_t w = fds->fds_bits[fd >> 6];
while (w) { while (w) {
unsigned o = _bsr(w); unsigned m = _bsr(w);
w &= ~((uint64_t)1 << o); w &= ~((uint64_t)1 << m);
if (fd + o < nfds) { if (fd + m < nfds) {
if (!gotsome) { if (!gotsome) {
gotsome = true; gotsome = true;
} else {
append(", "); append(", ");
append("%d", fd);
} }
append("%d", fd + m);
} }
} }
} }

View file

@ -53,7 +53,7 @@ static struct {
const char *tmpdir; const char *tmpdir;
} g_execve; } g_execve;
bool IsApeFile(const char *path) { static bool IsApeFile(const char *path) {
if (endswith(path, ".com")) { if (endswith(path, ".com")) {
return true; return true;
} else { } else {

View file

@ -47,50 +47,78 @@
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
struct timeval *timeout) { struct timeval *timeout) {
int rc; int rc;
struct timeval tv, *tvp; #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;
struct timeval old_timeout;
struct timeval *old_timeout_ptr = 0;
#endif
POLLTRACE("select(%d, %p, %p, %p, %s) → ...", nfds, readfds, writefds, POLLTRACE("select(%d, %p, %p, %p, %s) → ...", nfds, readfds, writefds,
exceptfds, DescribeTimeval(0, timeout)); exceptfds, DescribeTimeval(0, timeout));
// the linux kernel modifies timeout
if (timeout) {
if (IsAsan() && !__asan_is_valid(timeout, sizeof(*timeout))) {
return efault();
}
tv = *timeout;
tvp = &tv;
} else {
tvp = 0;
}
BEGIN_CANCELLATION_POINT; BEGIN_CANCELLATION_POINT;
if (nfds < 0) { if (nfds < 0) {
rc = einval(); rc = einval();
} else if (IsAsan() && } else if (IsAsan() &&
((readfds && !__asan_is_valid(readfds, FD_SIZE(nfds))) || ((readfds && !__asan_is_valid(readfds, FD_SIZE(nfds))) ||
(writefds && !__asan_is_valid(writefds, FD_SIZE(nfds))) || (writefds && !__asan_is_valid(writefds, FD_SIZE(nfds))) ||
(exceptfds && !__asan_is_valid(exceptfds, FD_SIZE(nfds))))) { (exceptfds && !__asan_is_valid(exceptfds, FD_SIZE(nfds))) ||
(timeout && !__asan_is_valid(timeout, sizeof(*timeout))))) {
rc = efault(); rc = efault();
} else if (!IsWindows()) {
#ifdef __aarch64__
struct timespec ts, *tsp;
if (timeout) {
ts.tv_sec = timeout->tv_sec;
ts.tv_nsec = timeout->tv_usec * 1000;
tsp = &ts;
} else {
tsp = 0;
}
rc = sys_pselect(nfds, readfds, writefds, exceptfds, tsp, 0);
#else
rc = sys_select(nfds, readfds, writefds, exceptfds, tvp);
#endif
} else { } else {
rc = sys_select_nt(nfds, readfds, writefds, exceptfds, 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;
}
if (timeout) {
old_timeout = *timeout;
old_timeout_ptr = &old_timeout;
}
#endif
if (!IsWindows()) {
#ifdef __aarch64__
struct timespec ts, *tsp;
if (timeout) {
ts = timeval_totimespec(*timeout);
tsp = &ts;
} else {
tsp = 0;
}
rc = sys_pselect(nfds, readfds, writefds, exceptfds, tsp, 0);
if (timeout) {
*timeout = timespec_totimeval(ts);
}
#else
rc = sys_select(nfds, readfds, writefds, exceptfds, timeout);
#endif
} else {
rc = sys_select_nt(nfds, readfds, writefds, exceptfds, timeout, 0);
}
} }
END_CANCELLATION_POINT; END_CANCELLATION_POINT;
STRACE("select(%d, [%s], [%s], [%s], [%s]) → %d% m", nfds, STRACE("select(%d, %s → [%s], %s → [%s], %s → [%s], %s → [%s]) → %d% m", nfds,
DescribeFdSet(rc, nfds, readfds), DescribeFdSet(rc, nfds, writefds), DescribeFdSet(rc, nfds, old_readfds_ptr),
DescribeFdSet(rc, nfds, exceptfds), DescribeTimeval(rc, tvp), rc); DescribeFdSet(rc, nfds, readfds),
DescribeFdSet(rc, nfds, old_writefds_ptr),
DescribeFdSet(rc, nfds, writefds),
DescribeFdSet(rc, nfds, old_exceptfds_ptr),
DescribeFdSet(rc, nfds, exceptfds), //
DescribeTimeval(rc, old_timeout_ptr), //
DescribeTimeval(rc, timeout), rc);
return rc; return rc;
} }