mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-06-28 15:28:30 +00:00
Improve quality of raise(), abort(), and tkill()
This change fixes a nasty bug where SIG_IGN and SIG_DFL weren't working as advertised on BSDs. This change also fixes the tkill() definition on MacOS so it maps to __pthread_kill().
This commit is contained in:
parent
c5659b93f8
commit
c5c4dfcd21
12 changed files with 293 additions and 63 deletions
|
@ -17,32 +17,45 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/getconsolectrlevent.internal.h"
|
||||
#include "libc/calls/sig.internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/calls/struct/sigset.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/calls/syscall_support-nt.internal.h"
|
||||
#include "libc/nt/console.h"
|
||||
#include "libc/nt/errors.h"
|
||||
#include "libc/nt/process.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/nt/synchronization.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/nexgen32e/threaded.h"
|
||||
#include "libc/runtime/internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/sicode.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/thread/xnu.internal.h"
|
||||
|
||||
static textwindows inline bool HasWorkingConsole(void) {
|
||||
return !!(__ntconsolemode[0] | __ntconsolemode[1] | __ntconsolemode[2]);
|
||||
}
|
||||
|
||||
static noubsan void RaiseSigFpe(void) {
|
||||
volatile int x = 0;
|
||||
x = 1 / x;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends signal to this thread.
|
||||
* Sends signal to self.
|
||||
*
|
||||
* This is basically the same as:
|
||||
*
|
||||
* tkill(gettid(), sig);
|
||||
*
|
||||
* Note `SIG_DFL` still results in process death for most signals.
|
||||
*
|
||||
* This function is not entirely equivalent to kill() or tkill(). For
|
||||
* example, we raise `SIGTRAP` and `SIGFPE` the natural way, since that
|
||||
* helps us support Windows. So if the raised signal has a signal
|
||||
* handler, then the reported `si_code` might not be `SI_TKILL`.
|
||||
*
|
||||
* On Windows, if a signal results in the termination of the process
|
||||
* then we use the convention `_Exit(128 + sig)` to notify the parent of
|
||||
* the signal number.
|
||||
*
|
||||
* @param sig can be SIGALRM, SIGINT, SIGTERM, SIGKILL, etc.
|
||||
* @return 0 on success or -1 w/ errno
|
||||
* @return 0 if signal was delivered and returned, or -1 w/ errno
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
int raise(int sig) {
|
||||
|
@ -52,28 +65,12 @@ int raise(int sig) {
|
|||
DebugBreak();
|
||||
rc = 0;
|
||||
} else if (sig == SIGFPE) {
|
||||
volatile int x = 0;
|
||||
x = 1 / x;
|
||||
RaiseSigFpe();
|
||||
rc = 0;
|
||||
} else if (!IsWindows()) {
|
||||
rc = sys_tkill(gettid(), sig, 0);
|
||||
} else {
|
||||
if (HasWorkingConsole() && (event = GetConsoleCtrlEvent(sig)) != -1) {
|
||||
// XXX: MSDN says "If this parameter is zero, the signal is
|
||||
// generated in all processes that share the console of the
|
||||
// calling process." which seems to imply multiple process
|
||||
// groups potentially. We just shouldn't use this because it
|
||||
// doesn't make any sense and it's so evil.
|
||||
if (GenerateConsoleCtrlEvent(event, 0)) {
|
||||
SleepEx(100, true);
|
||||
__sig_check(false);
|
||||
rc = 0;
|
||||
} else {
|
||||
rc = __winerr();
|
||||
}
|
||||
} else {
|
||||
rc = __sig_raise(sig, SI_USER);
|
||||
}
|
||||
rc = __sig_raise(sig, SI_TKILL);
|
||||
}
|
||||
STRACE("...raise(%G) → %d% m", sig, rc);
|
||||
return rc;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue