mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-02-07 06:53:33 +00:00
Discard ignored signals on New Technology (#592)
This commit is contained in:
parent
4b4ea046c4
commit
7de2f229a7
4 changed files with 57 additions and 1 deletions
|
@ -31,6 +31,7 @@ bool __sig_handle(bool, int, int, ucontext_t *) hidden;
|
|||
int __sig_add(int, int) hidden;
|
||||
int __sig_mask(int, const sigset_t *, sigset_t *) hidden;
|
||||
int __sig_raise(int, int) hidden;
|
||||
void __sig_check_ignore(const int, const unsigned) hidden;
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
|
|
|
@ -246,7 +246,7 @@ textwindows int __sig_add(int sig, int si_code) {
|
|||
}
|
||||
|
||||
/**
|
||||
* Enqueues generic signal for delivery on New Technology.
|
||||
* Checks for unblocked signals and delivers them on New Technology.
|
||||
*
|
||||
* @param restartable is for functions like read() but not poll()
|
||||
* @return true if EINTR should be returned by caller
|
||||
|
@ -264,3 +264,38 @@ textwindows bool __sig_check(bool restartable) {
|
|||
}
|
||||
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_isfatal(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(false, cur->sig, cur->si_code, 0);
|
||||
__sig_free(cur);
|
||||
} else {
|
||||
prev = cur;
|
||||
}
|
||||
}
|
||||
__sig_unlock();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -258,6 +258,7 @@ static int __sigaction(int sig, const struct sigaction *act,
|
|||
if (act) {
|
||||
__sighandrvas[sig] = rva;
|
||||
__sighandflags[sig] = act->sa_flags;
|
||||
__sig_check_ignore(sig, rva);
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
|
|
|
@ -156,3 +156,22 @@ noubsan void ubsanTrumpsSystemsEngineering(void) {
|
|||
TEST(sigaction, sigFpe_handlerCanEditProcessStateAndRecoverExecution) {
|
||||
ubsanTrumpsSystemsEngineering();
|
||||
}
|
||||
|
||||
static unsigned OnSignalCnt = 0;
|
||||
void OnSignal(int sig, siginfo_t *si, void *ctx) {
|
||||
OnSignalCnt++;
|
||||
}
|
||||
|
||||
TEST(sigaction, ignoringSignalDiscardsSignal) {
|
||||
struct sigaction sa = {.sa_sigaction = OnSignal, .sa_flags = SA_SIGINFO};
|
||||
ASSERT_EQ(0, sigaction(SIGUSR1, &sa, NULL));
|
||||
sigset_t blocked;
|
||||
sigemptyset(&blocked);
|
||||
sigaddset(&blocked, SIGUSR1);
|
||||
ASSERT_EQ(0, sigprocmask(SIG_SETMASK, &blocked, NULL));
|
||||
ASSERT_EQ(0, raise(SIGUSR1));
|
||||
ASSERT_NE(SIG_ERR, signal(SIGUSR1, SIG_IGN));
|
||||
ASSERT_EQ(0, sigaction(SIGUSR1, &sa, NULL));
|
||||
ASSERT_EQ(0, sigprocmask(SIG_UNBLOCK, &blocked, NULL));
|
||||
EXPECT_EQ(0, OnSignalCnt);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue