mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-31 03:27:39 +00:00
Rewrite Windows signal delivery system
This commit is contained in:
parent
00084577a3
commit
81f391dd22
19 changed files with 66 additions and 333 deletions
|
@ -17,44 +17,35 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "ape/sections.internal.h"
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/sig.internal.h"
|
||||
#include "libc/calls/state.internal.h"
|
||||
#include "libc/calls/struct/sigaction.h"
|
||||
#include "libc/calls/struct/siginfo.h"
|
||||
#include "libc/calls/struct/sigset.h"
|
||||
#include "libc/calls/struct/ucontext.internal.h"
|
||||
#include "libc/calls/ucontext.h"
|
||||
#include "libc/intrin/describebacktrace.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
#include "libc/log/libfatal.internal.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/nexgen32e/stackframe.h"
|
||||
#include "libc/nt/console.h"
|
||||
#include "libc/nt/enum/context.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/nt/struct/context.h"
|
||||
#include "libc/nt/thread.h"
|
||||
#include "libc/runtime/internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/sa.h"
|
||||
#include "libc/sysv/consts/sicode.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/thread/tls.h"
|
||||
|
||||
#ifdef __x86_64__
|
||||
|
||||
/**
|
||||
* Returns true if signal default action is to end process.
|
||||
* Returns true if signal is ignored by default.
|
||||
*/
|
||||
textwindows bool __sig_is_fatal(int sig) {
|
||||
return !(sig == SIGURG || //
|
||||
textwindows bool __sig_is_ignored(int sig) {
|
||||
return sig == SIGURG || //
|
||||
sig == SIGCONT || //
|
||||
sig == SIGCHLD || //
|
||||
sig == SIGWINCH);
|
||||
sig == SIGWINCH;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -70,70 +61,14 @@ textwindows bool __sig_is_core(int sig) {
|
|||
sig == SIGXFSZ;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates piece of memory for storing pending signal.
|
||||
* @assume lock is held
|
||||
*/
|
||||
static textwindows struct Signal *__sig_alloc(void) {
|
||||
int i;
|
||||
struct Signal *res = 0;
|
||||
for (i = 0; i < ARRAYLEN(__sig.mem); ++i) {
|
||||
if (!__sig.mem[i].used) {
|
||||
__sig.mem[i].used = true;
|
||||
res = __sig.mem + i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns signal memory to static pool.
|
||||
*/
|
||||
static textwindows void __sig_free(struct Signal *mem) {
|
||||
mem->used = false;
|
||||
}
|
||||
|
||||
static inline textwindows int __sig_is_masked(int sig) {
|
||||
if (__tls_enabled) {
|
||||
return __get_tls()->tib_sigmask & (1ull << (sig - 1));
|
||||
} else {
|
||||
return __sig.sigmask & (1ull << (sig - 1));
|
||||
return __sig.mask & (1ull << (sig - 1));
|
||||
}
|
||||
}
|
||||
|
||||
textwindows int __sig_is_applicable(struct Signal *s) {
|
||||
return s->tid <= 0 || s->tid == gettid();
|
||||
}
|
||||
|
||||
/**
|
||||
* Dequeues signal that isn't masked.
|
||||
* @return signal or null if empty or none unmasked
|
||||
*/
|
||||
static textwindows struct Signal *__sig_remove(int sigops) {
|
||||
struct Signal *prev, *res;
|
||||
if (__sig.queue) {
|
||||
__sig_lock();
|
||||
for (prev = 0, res = __sig.queue; res; prev = res, res = res->next) {
|
||||
if (__sig_is_applicable(res) && //
|
||||
!__sig_is_masked(res->sig) && //
|
||||
!((sigops & kSigOpNochld) && res->sig == SIGCHLD)) {
|
||||
if (res == __sig.queue) {
|
||||
__sig.queue = res->next;
|
||||
} else if (prev) {
|
||||
prev->next = res->next;
|
||||
}
|
||||
res->next = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
__sig_unlock();
|
||||
} else {
|
||||
res = 0;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delivers signal to callback.
|
||||
*
|
||||
|
@ -168,7 +103,7 @@ bool __sig_deliver(int sigops, int sig, int sic, ucontext_t *ctx) {
|
|||
if (__tls_enabled) {
|
||||
oldmask = __get_tls()->tib_sigmask;
|
||||
} else {
|
||||
oldmask = __sig.sigmask;
|
||||
oldmask = __sig.mask;
|
||||
}
|
||||
if (ctx) {
|
||||
ctx->uc_sigmask = (sigset_t){{oldmask}};
|
||||
|
@ -179,7 +114,7 @@ bool __sig_deliver(int sigops, int sig, int sic, ucontext_t *ctx) {
|
|||
if (__tls_enabled) {
|
||||
__get_tls()->tib_sigmask |= 1ull << (sig - 1);
|
||||
} else {
|
||||
__sig.sigmask |= 1ull << (sig - 1);
|
||||
__sig.mask |= 1ull << (sig - 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -192,7 +127,7 @@ bool __sig_deliver(int sigops, int sig, int sic, ucontext_t *ctx) {
|
|||
if (__tls_enabled) {
|
||||
__get_tls()->tib_sigmask = oldmask;
|
||||
} else {
|
||||
__sig.sigmask = oldmask;
|
||||
__sig.mask = oldmask;
|
||||
}
|
||||
if (flags & SA_RESETHAND) {
|
||||
__sighandrvas[sig] = (int32_t)(intptr_t)SIG_DFL;
|
||||
|
@ -213,17 +148,25 @@ bool __sig_deliver(int sigops, int sig, int sic, ucontext_t *ctx) {
|
|||
* @return true if `EINTR` should be raised
|
||||
*/
|
||||
textwindows bool __sig_handle(int sigops, int sig, int sic, ucontext_t *ctx) {
|
||||
if (__sighandrvas[sig] == (intptr_t)SIG_IGN ||
|
||||
(__sighandrvas[sig] == (intptr_t)SIG_DFL && __sig_is_ignored(sig))) {
|
||||
return false;
|
||||
}
|
||||
if (__sig_is_masked(sig)) {
|
||||
if (sigops & kSigOpUnmaskable) {
|
||||
goto DefaultAction;
|
||||
}
|
||||
__sig_add(0, sig, sic);
|
||||
if (__tls_enabled) {
|
||||
__get_tls()->tib_sigpending |= 1ull << (sig - 1);
|
||||
} else {
|
||||
__sig.pending |= 1ull << (sig - 1);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
switch (__sighandrvas[sig]) {
|
||||
case (intptr_t)SIG_DFL:
|
||||
DefaultAction:
|
||||
if (__sig_is_fatal(sig)) {
|
||||
if (!__sig_is_ignored(sig)) {
|
||||
uint32_t cmode;
|
||||
intptr_t hStderr;
|
||||
const char *signame;
|
||||
|
@ -254,40 +197,15 @@ textwindows bool __sig_handle(int sigops, int sig, int sic, ucontext_t *ctx) {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueues generic signal for delivery on New Technology.
|
||||
* @return 0 on success, otherwise -1 w/ errno
|
||||
* @threadsafe
|
||||
*/
|
||||
textwindows int __sig_add(int tid, int sig, int si_code) {
|
||||
int rc;
|
||||
struct Signal *mem;
|
||||
if (1 <= sig && sig <= 64) {
|
||||
if (__sighandrvas[sig] == (unsigned)(uintptr_t)SIG_IGN ||
|
||||
(__sighandrvas[sig] == (unsigned)(uintptr_t)SIG_DFL &&
|
||||
!__sig_is_fatal(sig))) {
|
||||
STRACE("ignoring %G", sig);
|
||||
rc = 0;
|
||||
} else {
|
||||
STRACE("enqueuing %G", sig);
|
||||
__sig_lock();
|
||||
++__sig_count;
|
||||
if ((mem = __sig_alloc())) {
|
||||
mem->tid = tid;
|
||||
mem->sig = sig;
|
||||
mem->si_code = si_code;
|
||||
mem->next = __sig.queue;
|
||||
__sig.queue = mem;
|
||||
rc = 0;
|
||||
} else {
|
||||
rc = enomem();
|
||||
static textwindows bool __sig_checkem(int sigops, uint64_t *pending) {
|
||||
bool res = false;
|
||||
for (int sig = 1; sig <= 64; ++sig) {
|
||||
if (*pending & (1ull << (sig - 1))) {
|
||||
*pending &= ~(1ull << (sig - 1));
|
||||
res |= __sig_handle(sigops, sig, SI_KERNEL, 0);
|
||||
}
|
||||
__sig_unlock();
|
||||
}
|
||||
} else {
|
||||
rc = einval();
|
||||
}
|
||||
return rc;
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -297,49 +215,11 @@ textwindows int __sig_add(int tid, int sig, int si_code) {
|
|||
* @threadsafe
|
||||
*/
|
||||
textwindows bool __sig_check(int sigops) {
|
||||
bool delivered;
|
||||
struct Signal *sig;
|
||||
delivered = false;
|
||||
while ((sig = __sig_remove(sigops))) {
|
||||
delivered |= __sig_handle(sigops, sig->sig, sig->si_code, 0);
|
||||
__sig_free(sig);
|
||||
}
|
||||
return delivered;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if a signal should be ignored and if so discards existing
|
||||
* instances of said signal on New Technology.
|
||||
*
|
||||
* Even blocked signals are discarded.
|
||||
*
|
||||
* @param sig the signal number to remove
|
||||
* @threadsafe
|
||||
*/
|
||||
textwindows void __sig_check_ignore(const int sig, const unsigned rva) {
|
||||
struct Signal *cur, *prev, *next;
|
||||
if (rva != (unsigned)(intptr_t)SIG_IGN &&
|
||||
(rva != (unsigned)(intptr_t)SIG_DFL || __sig_is_fatal(sig))) {
|
||||
return;
|
||||
}
|
||||
if (__sig.queue) {
|
||||
__sig_lock();
|
||||
for (prev = 0, cur = __sig.queue; cur; cur = next) {
|
||||
next = cur->next;
|
||||
if (sig == cur->sig) {
|
||||
if (cur == __sig.queue) {
|
||||
__sig.queue = cur->next;
|
||||
} else if (prev) {
|
||||
prev->next = cur->next;
|
||||
}
|
||||
__sig_handle(0, cur->sig, cur->si_code, 0);
|
||||
__sig_free(cur);
|
||||
} else {
|
||||
prev = cur;
|
||||
}
|
||||
}
|
||||
__sig_unlock();
|
||||
bool res = false;
|
||||
if (__tls_enabled) {
|
||||
res |= __sig_checkem(sigops, &__get_tls()->tib_sigpending);
|
||||
}
|
||||
return res | __sig_checkem(sigops, &__sig.pending);
|
||||
}
|
||||
|
||||
#endif /* __x86_64__ */
|
||||
|
|
|
@ -33,7 +33,7 @@ textwindows int __sig_mask(int how, const sigset_t *neu, sigset_t *old) {
|
|||
if (__tls_enabled) {
|
||||
mask = &__get_tls()->tib_sigmask;
|
||||
} else {
|
||||
mask = &__sig.sigmask;
|
||||
mask = &__sig.mask;
|
||||
}
|
||||
if (old) {
|
||||
old->__bits[0] = *mask;
|
||||
|
|
|
@ -1,47 +0,0 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2022 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/sig.internal.h"
|
||||
#include "libc/calls/state.internal.h"
|
||||
#include "libc/calls/struct/sigset.h"
|
||||
|
||||
#ifdef __x86_64__
|
||||
|
||||
/**
|
||||
* Determines the pending signals on New Technology.
|
||||
*
|
||||
* @param pending is to hold the pending signals
|
||||
* @threadsafe
|
||||
*/
|
||||
textwindows void __sig_pending(sigset_t *pending) {
|
||||
struct Signal *s;
|
||||
sigemptyset(pending);
|
||||
if (__sig.queue) {
|
||||
__sig_lock();
|
||||
for (s = __sig.queue; s; s = s->next) {
|
||||
if (__sig_is_applicable(s) &&
|
||||
__sighandrvas[s->sig] != (unsigned)(intptr_t)SIG_IGN) {
|
||||
sigaddset(pending, s->sig);
|
||||
}
|
||||
}
|
||||
__sig_unlock();
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* __x86_64__ */
|
|
@ -53,7 +53,7 @@ textwindows int sys_getrusage_nt(int who, struct rusage *usage) {
|
|||
.ru_majflt = memcount.PageFaultCount,
|
||||
.ru_inblock = iocount.ReadOperationCount,
|
||||
.ru_oublock = iocount.WriteOperationCount,
|
||||
.ru_nsignals = __sig_count,
|
||||
.ru_nsignals = __sig.count,
|
||||
};
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ static textwindows int GetSig(uint32_t dwCtrlType) {
|
|||
case kNtCtrlShutdownEvent: // only received by services
|
||||
return SIGHUP;
|
||||
default:
|
||||
__builtin_unreachable();
|
||||
return SIGSTKFLT;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -60,7 +60,7 @@ textwindows bool32 __sig_notify(int sig, int sic) {
|
|||
// if we don't have tls, then we can't hijack a safe stack from a
|
||||
// thread so just try our luck punting the signal to the next i/o
|
||||
if (!__tls_enabled) {
|
||||
__sig_add(0, sig, sic);
|
||||
__sig.pending |= 1ull << (sig - 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -79,7 +79,7 @@ textwindows bool32 __sig_notify(int sig, int sic) {
|
|||
if (pt->tib->tib_sigmask & (1ull << (sig - 1))) continue; // masked
|
||||
if (pt->flags & PT_BLOCKED) {
|
||||
pthread_spin_unlock(&_pthread_lock);
|
||||
__sig_add(0, sig, sic);
|
||||
__sig.pending |= 1ull << (sig - 1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -98,9 +98,7 @@ textwindows bool32 __sig_notify(int sig, int sic) {
|
|||
if (tid <= 0) continue; // -1 means spawning, 0 means terminated
|
||||
if (pt->tib->tib_sigmask & (1ull << (sig - 1))) continue; // masked
|
||||
pthread_spin_unlock(&_pthread_lock);
|
||||
if (_pthread_signal(pt, sig, sic) == -1) {
|
||||
__sig_add(0, sig, sic);
|
||||
}
|
||||
_pthread_signal(pt, sig, sic);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -109,7 +107,8 @@ textwindows bool32 __sig_notify(int sig, int sic) {
|
|||
}
|
||||
|
||||
__msabi textwindows bool32 __onntconsoleevent(uint32_t dwCtrlType) {
|
||||
return __sig_notify(GetSig(dwCtrlType), SI_KERNEL);
|
||||
__sig_notify(GetSig(dwCtrlType), SI_KERNEL);
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif /* __x86_64__ */
|
||||
|
|
|
@ -40,7 +40,7 @@ textwindows void _check_sigalrm(void) {
|
|||
timeval_add(g_setitimer.it_value, g_setitimer.it_interval);
|
||||
} while (timeval_cmp(now, g_setitimer.it_value) > 0);
|
||||
}
|
||||
__sig_add(0, SIGALRM, SI_TIMER);
|
||||
__sig.pending |= 1ull << (SIGALRM - 1);
|
||||
}
|
||||
|
||||
textwindows void sys_setitimer_nt_reset(void) {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_CALLS_SIGNALS_INTERNAL_H_
|
||||
#define COSMOPOLITAN_LIBC_CALLS_SIGNALS_INTERNAL_H_
|
||||
#include "libc/atomic.h"
|
||||
#include "libc/calls/struct/sigset.h"
|
||||
#include "libc/calls/ucontext.h"
|
||||
#include "libc/nt/struct/context.h"
|
||||
|
@ -19,32 +18,19 @@ struct Delivery {
|
|||
struct NtContext *nc;
|
||||
};
|
||||
|
||||
struct Signal {
|
||||
struct Signal *next;
|
||||
bool used;
|
||||
int tid;
|
||||
int sig;
|
||||
int si_code;
|
||||
};
|
||||
|
||||
struct Signals {
|
||||
uint64_t sigmask; /* only if tls is disabled */
|
||||
struct Signal *queue;
|
||||
struct Signal mem[__SIG_QUEUE_LENGTH];
|
||||
uint64_t mask;
|
||||
uint64_t pending;
|
||||
uint64_t count;
|
||||
};
|
||||
|
||||
extern struct Signals __sig;
|
||||
extern atomic_long __sig_count;
|
||||
|
||||
bool __sig_check(int);
|
||||
bool __sig_is_core(int);
|
||||
bool __sig_is_fatal(int);
|
||||
bool __sig_is_ignored(int);
|
||||
bool __sig_handle(int, int, int, ucontext_t *);
|
||||
int __sig_add(int, int, int);
|
||||
int __sig_mask(int, const sigset_t *, sigset_t *);
|
||||
void __sig_check_ignore(const int, const unsigned);
|
||||
void __sig_pending(sigset_t *);
|
||||
int __sig_is_applicable(struct Signal *);
|
||||
bool __sig_deliver(int, int, int, ucontext_t *);
|
||||
int __sig_tramp(struct Delivery *);
|
||||
bool32 __sig_notify(int, int);
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
#include "libc/sysv/consts/sa.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/thread/tls.h"
|
||||
|
||||
#ifdef SYSDEBUG
|
||||
__static_yoink("strsignal"); // for kprintf()
|
||||
|
@ -264,7 +265,13 @@ static int __sigaction(int sig, const struct sigaction *act,
|
|||
__sighandrvas[sig] = rva;
|
||||
__sighandflags[sig] = act->sa_flags;
|
||||
if (IsWindows()) {
|
||||
__sig_check_ignore(sig, rva);
|
||||
if (rva == (intptr_t)SIG_IGN ||
|
||||
(rva == (intptr_t)SIG_DFL && __sig_is_ignored(sig))) {
|
||||
__sig.pending &= ~(1ull << (sig - 1));
|
||||
if (__tls_enabled) {
|
||||
__get_tls()->tib_sigpending &= ~(1ull << (sig - 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2022 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/sig.internal.h"
|
||||
|
||||
atomic_long __sig_count;
|
|
@ -1,38 +0,0 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2022 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/state.internal.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/thread/thread.h"
|
||||
|
||||
void(__sig_lock)(void) {
|
||||
pthread_mutex_lock(&__sig_lock_obj);
|
||||
}
|
||||
|
||||
void(__sig_unlock)(void) {
|
||||
pthread_mutex_unlock(&__sig_lock_obj);
|
||||
}
|
||||
|
||||
void __sig_funlock(void) {
|
||||
bzero(&__sig_lock_obj, sizeof(__sig_lock_obj));
|
||||
__sig_lock_obj._type = PTHREAD_MUTEX_RECURSIVE;
|
||||
}
|
||||
|
||||
__attribute__((__constructor__)) static void __sig_init(void) {
|
||||
pthread_atfork(__sig_lock, __sig_unlock, __sig_funlock);
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2022 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/state.internal.h"
|
||||
#include "libc/thread/thread.h"
|
||||
|
||||
pthread_mutex_t __sig_lock_obj;
|
|
@ -24,6 +24,7 @@
|
|||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/thread/tls.h"
|
||||
|
||||
/**
|
||||
* Determines the blocked pending signals
|
||||
|
@ -57,8 +58,7 @@ int sigpending(sigset_t *pending) {
|
|||
}
|
||||
}
|
||||
} else if (IsWindows()) {
|
||||
sigemptyset(pending);
|
||||
__sig_pending(pending);
|
||||
*pending = (sigset_t){{__sig.pending | __get_tls()->tib_sigpending}};
|
||||
rc = 0;
|
||||
} else {
|
||||
rc = enosys();
|
||||
|
|
|
@ -8,7 +8,6 @@ COSMOPOLITAN_C_START_
|
|||
extern int __vforked;
|
||||
extern bool __time_critical;
|
||||
extern pthread_mutex_t __fds_lock_obj;
|
||||
extern pthread_mutex_t __sig_lock_obj;
|
||||
extern unsigned __sighandrvas[NSIG + 1];
|
||||
extern unsigned __sighandflags[NSIG + 1];
|
||||
extern const struct NtSecurityAttributes kNtIsInheritable;
|
||||
|
@ -16,9 +15,6 @@ extern const struct NtSecurityAttributes kNtIsInheritable;
|
|||
void __fds_lock(void);
|
||||
void __fds_unlock(void);
|
||||
void __fds_funlock(void);
|
||||
void __sig_lock(void);
|
||||
void __sig_unlock(void);
|
||||
void __sig_funlock(void);
|
||||
|
||||
#define __vforked (__tls_enabled && (__get_tls()->tib_flags & TIB_FLAG_VFORKED))
|
||||
|
||||
|
|
|
@ -49,11 +49,8 @@ static dontinline textwindows int __tkill_nt(int tid, int sig,
|
|||
}
|
||||
|
||||
// check if caller is killing themself
|
||||
if (tid == gettid() && __tls_enabled && (!tib || tib == __get_tls())) {
|
||||
struct NtContext nc = {.ContextFlags = kNtContextAll};
|
||||
struct Delivery pkg = {0, sig, SI_TKILL, &nc};
|
||||
unassert(GetThreadContext(GetCurrentThread(), &nc));
|
||||
__sig_tramp(&pkg);
|
||||
if (tid == gettid() && (!tib || tib == __get_tls())) {
|
||||
__sig_handle(0, sig, SI_TKILL, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -70,7 +67,8 @@ static dontinline textwindows int __tkill_nt(int tid, int sig,
|
|||
pthread_spin_unlock(&_pthread_lock);
|
||||
if (status < kPosixThreadTerminated) {
|
||||
if (pt->flags & PT_BLOCKED) {
|
||||
return __sig_add(tid, sig, SI_TKILL);
|
||||
pt->tib->tib_sigpending |= 1ull << (sig - 1);
|
||||
return 0;
|
||||
} else {
|
||||
return _pthread_signal(pt, sig, SI_TKILL);
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "libc/nt/enum/exceptionhandleractions.h"
|
||||
#include "libc/nt/enum/signal.h"
|
||||
#include "libc/nt/enum/status.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/nt/struct/ntexceptionpointers.h"
|
||||
#include "libc/nt/thunk/msabi.h"
|
||||
#include "libc/sysv/consts/sa.h"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2022 Justine Alexandra Roberts Tunney │
|
||||
│ 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 │
|
|
@ -27,10 +27,10 @@ struct CosmoTib {
|
|||
_Atomic(int32_t) tib_tid; /* 0x38 transitions -1 → tid → 0 */
|
||||
int32_t tib_errno; /* 0x3c */
|
||||
uint64_t tib_flags; /* 0x40 */
|
||||
long __padding;
|
||||
int tib_ftrace; /* inherited */
|
||||
int tib_strace; /* inherited */
|
||||
uint64_t tib_sigmask; /* inherited */
|
||||
uint64_t tib_sigpending;
|
||||
void *tib_reserved4;
|
||||
void *tib_reserved5;
|
||||
void *tib_reserved6;
|
||||
|
|
|
@ -273,9 +273,6 @@ sig_atomic_t gotusr1;
|
|||
|
||||
void OnSigMask(int sig, struct siginfo *si, void *ctx) {
|
||||
ucontext_t *uc = ctx;
|
||||
#ifdef __x86_64__
|
||||
ASSERT_EQ(123, uc->uc_mcontext.r15);
|
||||
#endif
|
||||
sigaddset(&uc->uc_sigmask, sig);
|
||||
gotusr1 = true;
|
||||
}
|
||||
|
@ -288,9 +285,6 @@ TEST(uc_sigmask, signalHandlerCanChangeSignalMaskOfTrappedThread) {
|
|||
ASSERT_SYS(0, 0, sigprocmask(SIG_SETMASK, &want, &got));
|
||||
ASSERT_FALSE(sigismember(&got, SIGUSR1));
|
||||
ASSERT_SYS(0, 0, sigaction(SIGUSR1, &sa, &oldsa));
|
||||
#ifdef __x86_64__
|
||||
asm volatile("mov\t%0,%%r15" : : "i"(123) : "r15", "memory");
|
||||
#endif
|
||||
ASSERT_SYS(0, 0, raise(SIGUSR1));
|
||||
ASSERT_TRUE(gotusr1);
|
||||
ASSERT_SYS(0, 0, sigprocmask(SIG_SETMASK, 0, &got));
|
||||
|
|
|
@ -70,7 +70,7 @@ TEST(sigprocmask, testMultipleBlockedDeliveriesOfSameSignal) {
|
|||
EXPECT_EQ(0, n);
|
||||
EXPECT_EQ(0, sigprocmask(SIG_SETMASK, &old, NULL));
|
||||
EXPECT_EQ(0, sigaction(SIGUSR2, &oldusr2, 0));
|
||||
if (IsFreebsd() || IsWindows()) {
|
||||
if (IsFreebsd()) {
|
||||
EXPECT_EQ(2, n);
|
||||
} else {
|
||||
EXPECT_EQ(1, n);
|
||||
|
|
Loading…
Reference in a new issue