feat: add process termination codes and SYS_ABORT; whole-process abort() from any thread in libc and montauk-rt
This commit is contained in:
1 parent
f8b8f9610f
commit
278b208258
15 files changed
+126
-37
No files matched your search
@@ -288,6 +288,11 @@ namespace montauk::abi {
|
||||
static constexpr uint64_t FUTEX_WAIT_FOREVER = ~0ULL;
|
||||
static constexpr uint32_t FUTEX_WAKE_ALL = 0xFFFFFFFFu;
|
||||
|
||||
/* Abnormal termination from any thread: ends the whole process (every
|
||||
thread) with exit code TerminatedAborted (256+SIGABRT). SYS_EXIT from a
|
||||
sibling thread ends only that thread, so abort() needs its own call. */
|
||||
static constexpr uint64_t SYS_ABORT = 198; // () -> does not return
|
||||
|
||||
/* Kernel-owned process capabilities. User identities may namespace
|
||||
per-user resources, but never participate in authorization decisions. */
|
||||
static constexpr uint64_t CAP_PROCESS_ADMIN = 1ULL << 0;
|
||||
|
||||
@@ -221,6 +221,7 @@ extern "C" {
|
||||
#define MTK_SYS_CHILDIO_WRITEKEY_EX 195
|
||||
#define MTK_SYS_FUTEX_WAIT 196
|
||||
#define MTK_SYS_FUTEX_WAKE 197
|
||||
#define MTK_SYS_ABORT 198
|
||||
/* @SYSCALLS-END */
|
||||
|
||||
/* Syscall status codes (montauk/statuscodes.h for C++). */
|
||||
|
||||
@@ -101,6 +101,33 @@ inline const char* GetStatusExplanationText(StatusCode statusCode) {
|
||||
return GetStatusText(statusCode);
|
||||
}
|
||||
|
||||
// Process termination codes: what waitpid returns when the kernel ended the
|
||||
// process (crash, kill, abort) instead of it calling exit. 256 + POSIX
|
||||
// signal number, so normal exit codes (0..255) can never collide.
|
||||
// Analogous to kernel/src/Common/TerminationCodes.hpp; same values.
|
||||
typedef enum {
|
||||
TerminationBase = 256,
|
||||
TerminatedIllegalInstruction = TerminationBase + 4, // SIGILL
|
||||
TerminatedBreakpoint = TerminationBase + 5, // SIGTRAP
|
||||
TerminatedAborted = TerminationBase + 6, // SIGABRT
|
||||
TerminatedArithmeticError = TerminationBase + 8, // SIGFPE
|
||||
TerminatedKilled = TerminationBase + 9, // SIGKILL
|
||||
TerminatedAccessViolation = TerminationBase + 11 // SIGSEGV
|
||||
} TerminationCode;
|
||||
|
||||
// Shared with C (libc.c), so no nullptr. Returns 0 for an unknown code.
|
||||
inline const char* GetTerminationText(int exitCode) {
|
||||
switch (exitCode) {
|
||||
case TerminatedIllegalInstruction: return "Illegal instruction";
|
||||
case TerminatedBreakpoint: return "Breakpoint";
|
||||
case TerminatedAborted: return "Aborted";
|
||||
case TerminatedArithmeticError: return "Arithmetic error";
|
||||
case TerminatedKilled: return "Killed";
|
||||
case TerminatedAccessViolation: return "Access violation";
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -527,6 +527,11 @@ namespace montauk {
|
||||
inline int kill(int pid) {
|
||||
return (int)syscall1(montauk::abi::SYS_KILL, (uint64_t)pid);
|
||||
}
|
||||
// End the whole process from any thread (exit code TerminatedAborted).
|
||||
[[noreturn]] inline void abort() {
|
||||
syscall0(montauk::abi::SYS_ABORT);
|
||||
__builtin_unreachable();
|
||||
}
|
||||
inline int setsession() {
|
||||
return (int)syscall0(montauk::abi::SYS_SETSESSION);
|
||||
}
|
||||
|
||||
@@ -130,6 +130,7 @@ static inline long _mtk_syscall4(long nr, long a1, long a2, long a3, long a4) {
|
||||
#define SYS_GETENVIRON 171
|
||||
#define SYS_SETENVIRON 172
|
||||
#define SYS_SPAWN_ENV 173
|
||||
#define SYS_ABORT 198
|
||||
|
||||
/* ========================================================================
|
||||
errno
|
||||
@@ -1243,9 +1244,9 @@ void exit(int status) {
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
/* Ends the whole process from any thread; waitpid sees WTERMSIG == SIGABRT. */
|
||||
void abort(void) {
|
||||
_mtk_syscall1(SYS_PRINT, (long)"abort() called\n");
|
||||
_mtk_syscall1(SYS_EXIT, 1);
|
||||
_mtk_syscall0(SYS_ABORT);
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
@@ -4055,8 +4056,8 @@ pid_t waitpid(pid_t pid, int *status, int options) {
|
||||
}
|
||||
long code = _mtk_syscall1(SYS_WAITPID, (long)pid);
|
||||
if (status != NULL) {
|
||||
if (code >= 256) {
|
||||
*status = (int)((code - 256) & 0x7F); /* signaled */
|
||||
if (code >= TerminationBase) {
|
||||
*status = (int)((code - TerminationBase) & 0x7F); /* signaled */
|
||||
} else {
|
||||
*status = (int)((code & 0xFF) << 8); /* exited */
|
||||
}
|
||||
|
||||
@@ -18,16 +18,12 @@ pub fn id() -> u32 {
|
||||
unsafe { sys::syscall0(sys::SYS_GETPID) as u32 }
|
||||
}
|
||||
|
||||
/// Terminate the whole process from any thread.
|
||||
/// Terminate the whole process from any thread. Waiters see exit code
|
||||
/// TerminatedAborted (256 + SIGABRT).
|
||||
pub fn abort() -> ! {
|
||||
unsafe {
|
||||
if crate::thread::current_id() == id() {
|
||||
sys::syscall1(sys::SYS_EXIT, 134);
|
||||
} else {
|
||||
// Sibling: SYS_EXIT would end only this thread. Self-kill flags
|
||||
// every thread; park here until the kernel reaps us.
|
||||
sys::syscall1(sys::SYS_KILL, id() as u64);
|
||||
}
|
||||
sys::syscall0(sys::SYS_ABORT);
|
||||
// Not reached. No panic here: the panic handler calls abort().
|
||||
loop {
|
||||
sys::syscall0(sys::SYS_YIELD);
|
||||
}
|
||||
|
||||
@@ -23,9 +23,9 @@ static void print_exit_code(const int exitCode) {
|
||||
if (code == 0) return;
|
||||
char buf[16];
|
||||
int n = 0;
|
||||
if (code >= 256) {
|
||||
if (code >= montauk::TerminationBase) {
|
||||
montauk::print("[terminated by signal ");
|
||||
code -= 256;
|
||||
code -= montauk::TerminationBase;
|
||||
} else {
|
||||
montauk::print("[exit code ");
|
||||
}
|
||||
@@ -39,13 +39,16 @@ static void print_exit_code(const int exitCode) {
|
||||
montauk::print(c);
|
||||
}
|
||||
|
||||
if (exitCode > 0 && exitCode <= montauk::MaxStatusCode) {
|
||||
const char* statusText = montauk::GetStatusText((montauk::StatusCode)exitCode);
|
||||
|
||||
if (statusText != nullptr) {
|
||||
montauk::print(" - ");
|
||||
montauk::print(statusText);
|
||||
}
|
||||
const char* statusText = nullptr;
|
||||
if (exitCode >= montauk::TerminationBase) {
|
||||
statusText = montauk::GetTerminationText(exitCode);
|
||||
} else if (exitCode > 0 && exitCode <= montauk::MaxStatusCode) {
|
||||
statusText = montauk::GetStatusText((montauk::StatusCode)exitCode);
|
||||
}
|
||||
|
||||
if (statusText != nullptr) {
|
||||
montauk::print(" - ");
|
||||
montauk::print(statusText);
|
||||
}
|
||||
|
||||
montauk::print("]\n");
|
||||
|
||||
Reference in new issue
Block a user