Attempt to fix MODE=dbg Windows execve() flake

This commit is contained in:
Justine Tunney committed 2025-01-05 14:05:49 -08:00
1 parent 7b67b20dae
commit 035b0e2a62
5 files changed
+68 -84

No files matched your search

+56 -53
View File
@@ -87,7 +87,7 @@ __msabi extern typeof(VirtualProtectEx) *const __imp_VirtualProtectEx;
__msabi extern typeof(VirtualQuery) *const __imp_VirtualQuery;
__msabi extern typeof(WriteFile) *const __imp_WriteFile;
extern pthread_mutex_t __sig_worker_lock;
atomic_int __sig_worker_state;
textwindows static bool __sig_ignored_by_default(int sig) {
return sig == SIGURG || //
@@ -742,39 +742,21 @@ HAIRY static uint32_t __sig_worker(void *arg) {
STKSZ, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_NOFORK);
for (;;) {
_pthread_mutex_lock(&__sig_worker_lock);
// ok sys_execve_nt() might disable this worker
if (~__sig_worker_state & 2) {
// dequeue all pending signals and fire them off. if there's no
// thread that can handle them then __sig_generate will requeue
// those signals back to __sig.process; hence the need for xchg
unsigned long sigs =
atomic_exchange_explicit(__sig.process, 0, memory_order_acq_rel);
while (sigs) {
int sig = bsfl(sigs) + 1;
sigs &= ~(1ull << (sig - 1));
__sig_generate(sig, SI_KERNEL);
}
// dequeue all pending signals and fire them off. if there's no
// thread that can handle them then __sig_generate will requeue
// those signals back to __sig.process; hence the need for xchg
unsigned long sigs =
atomic_exchange_explicit(__sig.process, 0, memory_order_acq_rel);
while (sigs) {
int sig = bsfl(sigs) + 1;
sigs &= ~(1ull << (sig - 1));
__sig_generate(sig, SI_KERNEL);
}
// unblock stalled i/o signals in threads
_pthread_lock();
for (struct Dll *e = dll_first(_pthread_list); e;
e = dll_next(_pthread_list, e)) {
struct PosixThread *pt = POSIXTHREAD_CONTAINER(e);
if (atomic_load_explicit(&pt->pt_status, memory_order_acquire) >=
kPosixThreadTerminated)
break;
if (atomic_load_explicit(&pt->pt_blocker, memory_order_acquire) &&
(atomic_load_explicit(&pt->tib->tib_sigpending,
memory_order_acquire) &
~atomic_load_explicit(&pt->pt_blkmask, memory_order_acquire)))
__sig_wake(pt, 0);
}
_pthread_unlock();
// unblock stalled asynchronous signals in threads
for (;;) {
sigset_t pending, mask;
struct PosixThread *mark = 0;
// unblock stalled i/o signals in threads
_pthread_lock();
for (struct Dll *e = dll_first(_pthread_list); e;
e = dll_next(_pthread_list, e)) {
@@ -782,34 +764,55 @@ HAIRY static uint32_t __sig_worker(void *arg) {
if (atomic_load_explicit(&pt->pt_status, memory_order_acquire) >=
kPosixThreadTerminated)
break;
pending = atomic_load_explicit(&pt->tib->tib_sigpending,
memory_order_acquire);
mask =
atomic_load_explicit(&pt->tib->tib_sigmask, memory_order_acquire);
if (pending & ~mask) {
_pthread_ref(pt);
mark = pt;
break;
}
if (atomic_load_explicit(&pt->pt_blocker, memory_order_acquire) &&
(atomic_load_explicit(&pt->tib->tib_sigpending,
memory_order_acquire) &
~atomic_load_explicit(&pt->pt_blkmask, memory_order_acquire)))
__sig_wake(pt, 0);
}
_pthread_unlock();
if (!mark)
break;
while (!atomic_compare_exchange_weak_explicit(
&mark->tib->tib_sigpending, &pending, pending & ~mask,
memory_order_acq_rel, memory_order_relaxed)) {
// unblock stalled asynchronous signals in threads
for (;;) {
sigset_t pending, mask;
struct PosixThread *mark = 0;
_pthread_lock();
for (struct Dll *e = dll_first(_pthread_list); e;
e = dll_next(_pthread_list, e)) {
struct PosixThread *pt = POSIXTHREAD_CONTAINER(e);
if (atomic_load_explicit(&pt->pt_status, memory_order_acquire) >=
kPosixThreadTerminated)
break;
pending = atomic_load_explicit(&pt->tib->tib_sigpending,
memory_order_acquire);
mask =
atomic_load_explicit(&pt->tib->tib_sigmask, memory_order_acquire);
if (pending & ~mask) {
_pthread_ref(pt);
mark = pt;
break;
}
}
_pthread_unlock();
if (!mark)
break;
while (!atomic_compare_exchange_weak_explicit(
&mark->tib->tib_sigpending, &pending, pending & ~mask,
memory_order_acq_rel, memory_order_relaxed)) {
}
while ((pending = pending & ~mask)) {
int sig = bsfl(pending) + 1;
pending &= ~(1ull << (sig - 1));
__sig_killer(mark, sig, SI_KERNEL);
}
_pthread_unref(mark);
}
while ((pending = pending & ~mask)) {
int sig = bsfl(pending) + 1;
pending &= ~(1ull << (sig - 1));
__sig_killer(mark, sig, SI_KERNEL);
}
_pthread_unref(mark);
}
// wait until next scheduler quantum
_pthread_mutex_unlock(&__sig_worker_lock);
__sig_worker_state |= 1;
Sleep(POLL_INTERVAL_MS);
__sig_worker_state &= ~1;
}
__builtin_unreachable();
}
-22
View File
@@ -1,22 +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 2024 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/thread/thread.h"
// this mutex is needed so execve() can shut down the signal worker
pthread_mutex_t __sig_worker_lock = PTHREAD_MUTEX_INITIALIZER;
+8 -5
View File
@@ -17,6 +17,7 @@
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/assert.h"
#include "libc/atomic.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/sig.internal.h"
@@ -57,11 +58,10 @@
__msabi extern typeof(CloseHandle) *const __imp_CloseHandle;
__msabi extern typeof(TerminateProcess) *const __imp_TerminateProcess;
extern pthread_mutex_t __sig_worker_lock;
extern atomic_int __sig_worker_state;
static void sys_execve_nt_abort(sigset_t sigmask) {
_pthread_unlock();
_pthread_mutex_unlock(&__sig_worker_lock);
__sig_worker_state &= ~2;
__sig_unblock(sigmask);
}
@@ -70,8 +70,10 @@ textwindows int sys_execve_nt(const char *program, char *const argv[],
// execve() needs to be @asyncsignalsafe
sigset_t sigmask = __sig_block();
_pthread_mutex_lock(&__sig_worker_lock); // order matters
_pthread_lock(); // order matters
__sig_worker_state |= 2;
for (;;)
if (__sig_worker_state & 1)
break;
// new process should be a child of our parent
int64_t hParentProcess =
@@ -176,6 +178,7 @@ textwindows int sys_execve_nt(const char *program, char *const argv[],
STRACE("warning: execve() lingering due to non-cosmo parent process");
// terminate other threads
_pthread_lock();
struct Dll *e;
struct PosixThread *me = _pthread_self();
for (e = dll_first(_pthread_list); e; e = dll_next(_pthread_list, e)) {
+3 -2
View File
@@ -16,6 +16,7 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/atomic.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/sig.internal.h"
@@ -54,9 +55,9 @@
__msabi extern typeof(GetCurrentProcessId) *const __imp_GetCurrentProcessId;
extern atomic_int __sig_worker_state;
extern pthread_mutex_t __cxa_lock_obj;
extern pthread_mutex_t __pthread_lock_obj;
extern pthread_mutex_t __sig_worker_lock;
void __rand64_lock(void);
void __rand64_unlock(void);
@@ -191,7 +192,7 @@ static void fork_child(int ppid_win32, int ppid_cosmo) {
sys_read_nt_wipe_keystrokes();
__proc_wipe_and_reset();
__itimer_wipe_and_reset();
_pthread_mutex_wipe_np(&__sig_worker_lock);
atomic_init(&__sig_worker_state, 0);
if (_weaken(__sig_init))
_weaken(__sig_init)();
if (_weaken(sys_getppid_nt_wipe))
+1 -2
View File
@@ -58,8 +58,7 @@ TEST(execve, testArgPassing) {
FormatInt32(ibuf, i);
GenBuf(buf, i);
SPAWN(vfork);
execve(prog, (char *const[]){(char *)prog, "-", ibuf, buf, 0},
(char *const[]){0});
execl(prog, prog, "-", ibuf, buf, NULL);
kprintf("execve failed: %m\n");
EXITS(0);
}