feat: add process termination codes and SYS_ABORT; whole-process abort() from any thread in libc and montauk-rt

This commit is contained in:
daniel committed 2026-10-14 07:32:15 +02:00
1 parent f8b8f9610f
commit 278b208258
15 files changed
+126 -37

No files matched your search

+1 -1
View File
@@ -12,4 +12,4 @@
#pragma once
#define MONTAUK_BUILD_NUMBER 306
#define MONTAUK_BUILD_NUMBER 308
+10 -3
View File
@@ -220,10 +220,17 @@ namespace montauk::abi {
return count;
}
// Flag every thread of the caller's process with TerminatedAborted, then
// exit this one. A sibling's ExitProcess ends only itself; the main
// thread and the other siblings follow via killPending.
static void Sys_Abort() {
Sched::KillProcess(Sched::GetCurrentPid(), TerminatedAborted);
Sched::ExitProcess();
}
static int Sys_Kill(int pid) {
// A process may always kill itself: a sibling thread has no other
// way to take the whole process down (SYS_EXIT from a sibling ends
// only that thread), which abort()/panic=abort need.
// A process may always kill itself (kill(getpid(), ...)); waiters
// see TerminatedKilled. abort() uses SYS_ABORT instead.
if (pid == Sched::GetCurrentPid()) return Sched::KillProcess(pid);
if (!Sched::HasCapability(CAP_PROCESS_ADMIN)) {
int ancestor = pid;
+3
View File
@@ -400,6 +400,9 @@ namespace montauk::abi {
return (int64_t)Sys_ProcList((ProcInfo*)frame->arg1, (int)frame->arg2);
case SYS_KILL:
return (int64_t)Sys_Kill((int)frame->arg1);
case SYS_ABORT:
Sys_Abort();
return Success;
case SYS_SETSESSION:
return (int64_t)Sys_SetSession();
case SYS_KILLSESSION:
+5
View File
@@ -375,6 +375,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;
+37
View File
@@ -0,0 +1,37 @@
/*
* TerminationCodes.hpp
* MontaukOS process termination codes.
* Copyright (c) 2026 Daniel Hammer
*/
#pragma once
#include <cstdint>
// Exit code recorded when the kernel ends a process, as opposed to the
// process calling SYS_EXIT (which is masked to 0..255). Encoded as
// 256 + POSIX signal number so libc waitpid can report WTERMSIG.
// Mirrored in userspace at programs/include/montauk/statuscodes.h.
enum TerminationCodes {
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
};
// Termination code for a user-mode CPU exception. The exact vector is
// kept in the crash report; this is only the category.
inline TerminationCodes TerminationFromVector(uint8_t vector) {
switch (vector) {
case 0x06: return TerminatedIllegalInstruction; // #UD
case 0x01: // #DB
case 0x03: return TerminatedBreakpoint; // #BP
case 0x00: // #DE
case 0x10: // #MF
case 0x13: return TerminatedArithmeticError; // #XM
default: return TerminatedAccessViolation; // #PF, #GP, #SS, #NP, #AC, #OF, #BR, #CP, ...
}
}
+7 -9
View File
@@ -8,6 +8,7 @@
#include <Memory/Heap.hpp>
#include <Common/Panic.hpp>
#include <Common/TerminationCodes.hpp>
#include <Platform/Registers.hpp>
#include <CppLib/Stream.hpp>
#include <Memory/PageFrameAllocator.hpp>
@@ -170,23 +171,20 @@ namespace Hal {
CrashReport::AddReport(rep);
Sched::SpawnCrashPad(proc->pid);
// Record a killed-by-signal exit code (256+sig) so a parent
// blocked in SYS_WAITPID can tell a crash from a clean exit.
// Record a termination code (256+sig) so a parent blocked in
// SYS_WAITPID can tell a crash from a clean exit.
{
int sig = 11; /* SIGSEGV */
if (i == 0x00) sig = 8; /* #DE -> SIGFPE */
else if (i == 0x06) sig = 4; /* #UD -> SIGILL */
else if (i == 0x10 || i == 0x13) sig = 8; /* x87/SIMD FP */
int code = TerminationFromVector(i);
// ExitProcess from a sibling thread ends only that thread,
// which would leave the process running with the crash
// swallowed. Flag the whole process (main thread and every
// sibling) first, carrying the crash code rather than
// KillProcess's default SIGKILL, so waiters see the fault.
// KillProcess's default TerminatedKilled, so waiters see the fault.
if (Sched::GetCurrentThreadPtr() != proc) {
Sched::KillProcess(proc->pid, 256 + sig);
Sched::KillProcess(proc->pid, code);
} else {
Sched::SetProcessExitCode(proc->pid, 256 + sig);
Sched::SetProcessExitCode(proc->pid, code);
}
}
+1 -1
View File
@@ -1885,7 +1885,7 @@ namespace Sched {
continue;
}
primary.exitCode = 256 + 9; /* killed (SIGKILL) */
primary.exitCode = TerminatedKilled;
primary.killPending = true;
if (primary.state == ProcessState::Blocked) {
primary.state = ProcessState::Ready;
+3 -2
View File
@@ -6,6 +6,7 @@
#pragma once
#include <cstdint>
#include <Common/TerminationCodes.hpp>
#include <atomic>
#include <Api/Syscall.hpp>
@@ -303,9 +304,9 @@ namespace Sched {
// Kill a process by PID. If the process is running on another CPU,
// sets a kill-pending flag checked on the next timer tick. exitCode is
// what a waiter sees (256+sig; SIGKILL by default).
// what a waiter sees (a TerminationCodes value).
// Returns 0 on success, -1 on failure.
int KillProcess(int pid, int exitCode = 256 + 9);
int KillProcess(int pid, int exitCode = TerminatedKilled);
// Start a new process session for the caller, or terminate every process
// belonging to a session. KillSession returns the number of live members