POSIX-compliant signal handling subsystem for mCertikos
- Asynchronous process notification via 32 signal types
- Custom signal handlers with safe context save/restore
- Kernel-injected trampoline for automatic
sigreturn - Full SIGKILL/SIGINT/SIGFPE support
- Hardware exception isolation (division by zero recovery)
Signal provides a mechanism for the kernel to interrupt user processes and notify them of events. Processes can register custom handlers, block signals, or rely on default actions. The implementation follows POSIX semantics and integrates with mCertikos trap handling.
- Installation
- Quick Start
- Architecture
- API Reference
- Trampoline
- sys_kill Flow
- Signal Reference
- Files
- Testing
make
make qemuRegister a handler and send a signal:
#include <signal.h>
void handler(int sig) {
printf("Caught signal %d\n", sig);
}
int main() {
struct sigaction sa = { .sa_handler = handler };
sigaction(SIGUSR1, &sa, NULL);
pause(); // Wait for signal
return 0;
}From shell:
kill 10 <pid> # Send SIGUSR1
kill 9 <pid> # Terminate process
+-------------+ signal +-------------+ trap +-------------+
| Process | <----------- | Kernel | <---------- | Hardware |
+-------------+ +-------------+ +-------------+
| |
| handler() | pending_signals |= (1 << sig)
v |
+-------------+ +-------------+
| Trampoline | -----------> | sigreturn |
+-------------+ int 0x30 +-------------+
- Event triggers signal (keyboard, exception,
kill()) - Kernel sets pending bit in target TCB
- On trap return, kernel checks pending signals
- Kernel saves context, sets up stack frame, redirects to handler
- Handler executes and returns
- Trampoline invokes
sys_sigreturn - Kernel restores context, process resumes
| Call | Description |
|---|---|
sigaction(sig, act, oldact) |
Register handler |
kill(pid, sig) |
Send signal |
pause() |
Block until signal |
sigreturn() |
Restore context (internal) |
struct sigaction {
sighandler_t sa_handler;
uint32_t sa_mask;
int sa_flags;
void (*sa_restorer)(void);
};
struct sig_state {
struct sigaction sigactions[NSIG];
uint32_t pending_signals;
int signal_block_mask;
};The trampoline is a 7-byte stub injected onto the user stack. It ensures handlers return to kernel via sigreturn.
- Automatic context restoration after handler
- POSIX compliance without user cooperation
- Safe return path from any handler
movl $29, %eax ; SYS_sigreturn
int $0x30 ; trap to kerneluint8_t trampoline[7] = {
0xB8, 0x1D, 0x00, 0x00, 0x00, // mov $29, %eax
0xCD, 0x30 // int $0x30
};uint32_t sp = tf->esp;
sp -= 7;
memcpy((void*)sp, trampoline, 7);
uint32_t ret_addr = sp;
sp -= 4; *(uint32_t*)sp = ret_addr; // return address
sp -= 4; *(uint32_t*)sp = signum; // argument
tf->esp = sp;
tf->eip = (uint32_t)handler;- Kernel receives syscall 29
- Retrieves saved context from TCB
- Restores EIP, ESP, registers
- Clears handler flag
- Returns to interrupted code
int sys_kill(int pid, int signum) {
if (signum < 1 || signum >= NSIG) return -1;
if (pid <= 0) return -1;
struct TCB *target = tcb_get(pid);
if (!target || target->state == TSTATE_DEAD) return -1;
if (signum == SIGKILL) {
target->state = TSTATE_DEAD;
thread_remove_from_queue(pid);
return 0;
}
target->sigstate.pending_signals |= (1 << signum);
if (target->state == TSTATE_SLEEP) {
target->state = TSTATE_READY;
thread_add_to_queue(pid);
}
return 0;
}kill(pid, sig)
|
v
Validate -----> Error
|
v
SIGKILL? --yes--> Terminate
|
no
v
Set pending
|
v
Wake if sleeping
|
v
return 0
| Signal | Num | Action | Catchable |
|---|---|---|---|
| SIGHUP | 1 | Term | Yes |
| SIGINT | 2 | Term | Yes |
| SIGQUIT | 3 | Term | Yes |
| SIGILL | 4 | Term | Yes |
| SIGFPE | 8 | Term | Yes |
| SIGKILL | 9 | Term | No |
| SIGUSR1 | 10 | Term | Yes |
| SIGSEGV | 11 | Term | Yes |
| SIGUSR2 | 12 | Term | Yes |
| SIGTERM | 15 | Term | Yes |
| SIGCHLD | 17 | Ign | Yes |
| SIGSTOP | 19 | Stop | No |
kern/
lib/signal.h # Signal definitions
trap/TSyscall/TSyscall.c # Syscall implementations
trap/TDispatch/TDispatch.c
trap/TTrapHandler/TTrapHandler.c
thread/PTCBIntro/PTCBIntro.c
user/
include/signal.h # User interface
lib/signal.c # Library wrappers
+-----------+ +-----------+
| Parent | -- kill(child) --> | Child |
| | | handler |
| | <-- kill(parent) -- | |
| handler | | |
+-----------+ +-----------+
| |
+------ trampoline/sigreturn ------+
| |
v v
resume resume