mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-03-15 05:16:30 +00:00
Attempt to fix MODE=dbg Windows execve() flake
This commit is contained in:
parent
7b67b20dae
commit
035b0e2a62
5 changed files with 68 additions and 84 deletions
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
|
@ -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)) {
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue