diff --git a/libc/calls/park.c b/libc/calls/park.c index dcd4458d1..55aae00bf 100644 --- a/libc/calls/park.c +++ b/libc/calls/park.c @@ -57,7 +57,7 @@ textwindows static int _park_thread(uint32_t msdelay, sigset_t waitmask, CloseHandle(sigev); // recursion is now safe - if (ws == -1) + if (ws == -1u) return __winerr(); int handler_was_called = 0; if (sig) diff --git a/libc/calls/poll-nt.c b/libc/calls/poll-nt.c index 339bea6ff..23a54ffb5 100644 --- a/libc/calls/poll-nt.c +++ b/libc/calls/poll-nt.c @@ -17,6 +17,7 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/internal.h" +#include "libc/calls/sig.internal.h" #include "libc/calls/state.internal.h" #include "libc/calls/struct/sigset.h" #include "libc/calls/struct/sigset.internal.h" @@ -25,6 +26,7 @@ #include "libc/calls/syscall_support-nt.internal.h" #include "libc/intrin/atomic.h" #include "libc/intrin/fds.h" +#include "libc/intrin/weaken.h" #include "libc/macros.h" #include "libc/nt/console.h" #include "libc/nt/enum/filetype.h" @@ -41,6 +43,7 @@ #include "libc/sock/internal.h" #include "libc/sock/struct/pollfd.h" #include "libc/sysv/consts/o.h" +#include "libc/sysv/consts/sicode.h" #include "libc/sysv/errfuns.h" #include "libc/thread/posixthread.internal.h" #ifdef __x86_64__ @@ -84,7 +87,7 @@ textwindows static int sys_poll_nt_actual(struct pollfd *fds, uint64_t nfds, struct PosixThread *pt; int i, rc, ev, kind, gotsocks; struct sys_pollfd_nt sockfds[64]; - uint32_t cm, fi, wi, sn, pn, avail, waitfor, already_slept; + uint32_t cm, fi, sn, pn, avail, waitfor, already_slept; // ensure revents is cleared for (i = 0; i < nfds; ++i) @@ -228,22 +231,36 @@ textwindows static int sys_poll_nt_actual(struct pollfd *fds, uint64_t nfds, // this ensures low latency for apps like emacs which with no sock // here we shall actually report that something can be written too if (!already_slept) { - if (__sigcheck(waitmask, false)) - return -1; + intptr_t sigev; + if (!(sigev = CreateEvent(0, 0, 0, 0))) + return __winerr(); + filehands[pn] = sigev; pt = _pthread_self(); - filehands[pn] = pt->pt_event = CreateEvent(0, 0, 0, 0); + pt->pt_event = sigev; + pt->pt_blkmask = waitmask; atomic_store_explicit(&pt->pt_blocker, PT_BLOCKER_EVENT, memory_order_release); - wi = WaitForMultipleObjects(pn + 1, filehands, 0, waitfor); + //!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!// + int sig = 0; + uint32_t wi = pn; + if (!_is_canceled() && + !(_weaken(__sig_get) && (sig = _weaken(__sig_get)(waitmask)))) + wi = WaitForMultipleObjects(pn + 1, filehands, 0, waitfor); + //!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!// atomic_store_explicit(&pt->pt_blocker, 0, memory_order_release); - CloseHandle(filehands[pn]); - if (wi == -1u) { + CloseHandle(sigev); + if (wi == -1u) // win32 wait failure return __winerr(); - } else if (wi == pn) { + if (wi == pn) { // our signal event was signalled - if (__sigcheck(waitmask, false)) + int handler_was_called = 0; + if (sig) + handler_was_called = _weaken(__sig_relay)(sig, SI_KERNEL, waitmask); + if (_check_cancel() == -1) return -1; + if (handler_was_called) + return eintr(); } else if ((wi ^ kNtWaitAbandoned) < pn) { // this is possibly because a process or thread was killed fds[fileindices[wi ^ kNtWaitAbandoned]].revents = POLLERR_; @@ -287,8 +304,6 @@ textwindows static int sys_poll_nt_actual(struct pollfd *fds, uint64_t nfds, } else { // should only be possible on kNtWaitTimeout or semaphore abandoned // keep looping for events and we'll catch timeout when appropriate - if (__sigcheck(waitmask, false)) - return -1; } } @@ -306,6 +321,13 @@ textwindows static int sys_poll_nt_impl(struct pollfd *fds, uint64_t nfds, uint32_t waitms; int i, n, rc, got = 0; + // we normally don't check for signals until we decide to wait, since + // it's nice to have functions like write() be unlikely to EINTR, but + // ppoll is a function where users are surely thinking about signals, + // since ppoll actually allows them to block signals everywhere else. + if (__sigcheck(waitmask, false)) + return -1; + // fast path if (nfds <= 63) return sys_poll_nt_actual(fds, nfds, deadline, waitmask); diff --git a/libc/calls/pselect.c b/libc/calls/pselect.c index 9ecf8490f..e154a773a 100644 --- a/libc/calls/pselect.c +++ b/libc/calls/pselect.c @@ -124,11 +124,11 @@ int pselect(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, END_CANCELATION_POINT; STRACE("pselect(%d, %s → [%s], %s → [%s], %s → [%s], %s, %s) → %d% m", nfds, - DescribeFdSet(rc, nfds, old_readfds_ptr), + DescribeFdSet(0, nfds, old_readfds_ptr), DescribeFdSet(rc, nfds, readfds), - DescribeFdSet(rc, nfds, old_writefds_ptr), + DescribeFdSet(0, nfds, old_writefds_ptr), DescribeFdSet(rc, nfds, writefds), - DescribeFdSet(rc, nfds, old_exceptfds_ptr), + DescribeFdSet(0, nfds, old_exceptfds_ptr), DescribeFdSet(rc, nfds, exceptfds), // DescribeTimespec(0, timeout), // DescribeSigset(0, sigmask), rc); diff --git a/libc/intrin/describefdset.c b/libc/intrin/describefdset.c index 62ffccaad..7241b00db 100644 --- a/libc/intrin/describefdset.c +++ b/libc/intrin/describefdset.c @@ -31,6 +31,8 @@ const char *_DescribeFdSet(char buf[N], ssize_t rc, int nfds, fd_set *fds) { if (!fds) return "NULL"; + if (rc == -1) + return "n/a"; if (kisdangerous(fds)) { ksnprintf(buf, N, "%p", fds); return buf; diff --git a/libc/proc/proc.c b/libc/proc/proc.c index bf3d08a75..df9fee0c1 100644 --- a/libc/proc/proc.c +++ b/libc/proc/proc.c @@ -102,14 +102,14 @@ textwindows int __proc_harvest(struct Proc *pr, bool iswait4) { pr->handle = status & 0x00FFFFFF; } else { // handle child _Exit() - if (status == 0xc9af3d51u) { + if (status == 0xc9af3d51u) status = kNtStillActive; - } pr->wstatus = status; if (!iswait4 && !pr->waiters && !__proc.waiters && (__sighandrvas[SIGCHLD] == (uintptr_t)SIG_IGN || (__sighandflags[SIGCHLD] & SA_NOCLDWAIT))) { // perform automatic zombie reaping + STRACE("automatically reaping zombie"); dll_remove(&__proc.list, &pr->elem); dll_make_first(&__proc.free, &pr->elem); CloseHandle(pr->handle); @@ -192,9 +192,8 @@ static textwindows dontinstrument uint32_t __proc_worker(void *arg) { continue; if (j == i) continue; - if (!--objects[j]->waiters && objects[j]->status == PROC_UNDEAD) { + if (!--objects[j]->waiters && objects[j]->status == PROC_UNDEAD) __proc_free(objects[j]); - } } // check if we need to churn due to >64 processes @@ -219,9 +218,8 @@ static textwindows dontinstrument uint32_t __proc_worker(void *arg) { case PROC_ZOMBIE: break; case PROC_UNDEAD: - if (!objects[i]->waiters) { + if (!objects[i]->waiters) __proc_free(objects[i]); - } break; default: __builtin_unreachable(); @@ -233,9 +231,8 @@ static textwindows dontinstrument uint32_t __proc_worker(void *arg) { // 1. wait4() is being used // 2. SIGCHLD has SIG_IGN handler // 3. SIGCHLD has SA_NOCLDWAIT flag - if (sic) { + if (sic) __sig_generate(SIGCHLD, sic); - } } return 0; } diff --git a/test/libc/calls/fchmod_test.c b/test/libc/calls/fchmod_test.c deleted file mode 100644 index df8ffcc2b..000000000 --- a/test/libc/calls/fchmod_test.c +++ /dev/null @@ -1,41 +0,0 @@ -/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│ vi: set et 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/calls.h" -#include "libc/calls/struct/stat.h" -#include "libc/testlib/testlib.h" - -void SetUpOnce(void) { - testlib_enable_tmp_setup_teardown(); -} - -uint32_t GetMode(int fd) { - struct stat st; - ASSERT_SYS(0, 0, fstat(fd, &st)); - return st.st_mode & 0777; -} - -TEST(fchmod, canChangeReadOnlyBit) { - ASSERT_SYS(0, 3, creat("foo", 0600)); - ASSERT_EQ(0600, GetMode(3)); - ASSERT_SYS(0, 0, fchmod(3, 0400)); - ASSERT_EQ(0400, GetMode(3)); - ASSERT_SYS(0, 0, fchmod(3, 0600)); - ASSERT_EQ(0600, GetMode(3)); - ASSERT_SYS(0, 0, close(3)); -}