std.signals
UNIX-Signalbehandlung (WP-3): Registriert Handler-Funktionen für POSIX-Signale, steuert die Signal-Maske eines Threads und ermöglicht den fd-basierten Signal-Empfang via signalfd (epoll-kompatibel). Alle 31 Standard-Signale sind als Konstanten verfügbar.
→ Standard Library · std.process · std.net.epoll
Konstanten
Signalnummern
| Konstante | Nr. | Standardverhalten | Beschreibung |
SIGHUP | 1 | Beenden | Terminal getrennt oder Daemon-Reload |
SIGINT | 2 | Beenden | Tastatur-Interrupt (Strg+C) |
SIGQUIT | 3 | Core | Tastatur-Quit (Strg+\) |
SIGILL | 4 | Core | Ungültige CPU-Instruktion |
SIGTRAP | 5 | Core | Trace-/Breakpoint-Trap |
SIGABRT | 6 | Core | Abnormaler Abbruch (abort()) |
SIGBUS | 7 | Core | Ungültiger Speicherzugriff (Alignment) |
SIGFPE | 8 | Core | Gleitkomma-/Arithmetikfehler |
SIGKILL | 9 | Beenden | Sofort beenden (nicht abfangbar) |
SIGUSR1 | 10 | Beenden | Benutzerdefiniertes Signal 1 |
SIGSEGV | 11 | Core | Ungültiger Speicherzugriff |
SIGUSR2 | 12 | Beenden | Benutzerdefiniertes Signal 2 |
SIGPIPE | 13 | Beenden | Schreiben in geschlossene Pipe |
SIGALRM | 14 | Beenden | Timer abgelaufen (alarm()) |
SIGTERM | 15 | Beenden | Normales Beendigungs-Signal |
SIGSTKFLT | 16 | Beenden | Stack-Fehler (Koprozessor) |
SIGCHLD | 17 | Ignorieren | Kindprozess beendet oder gestoppt |
SIGCONT | 18 | Fortsetzen | Gestoppten Prozess fortsetzen |
SIGSTOP | 19 | Stoppen | Prozess anhalten (nicht abfangbar) |
SIGTSTP | 20 | Stoppen | Tastatur-Stop (Strg+Z) |
SIGTTIN | 21 | Stoppen | Hintergrundprozess liest Terminal |
SIGTTOU | 22 | Stoppen | Hintergrundprozess schreibt Terminal |
SIGURG | 23 | Ignorieren | Dringende Daten auf Socket (OOB) |
SIGXCPU | 24 | Core | CPU-Zeitlimit überschritten |
SIGXFSZ | 25 | Core | Dateigrößen-Limit überschritten |
SIGVTALRM | 26 | Beenden | Virtueller Timer (Userspace-Zeit) |
SIGPROF | 27 | Beenden | Profiling-Timer |
SIGWINCH | 28 | Ignorieren | Terminal-Größe geändert |
SIGIO | 29 | Beenden | I/O-Ereignis auf fd |
SIGPWR | 30 | Beenden | Stromausfall |
SIGSYS | 31 | Core | Ungültiger Syscall |
Standard-Handler
| Konstante | Wert | Beschreibung |
SIG_DFL | 0 | Standard-Verhalten wiederherstellen |
SIG_IGN | 1 | Signal dauerhaft ignorieren |
sigaction-Struktur
| Offset | Feld | Typ | Beschreibung |
| +0 | sa_handler | int64 | Handler-Adresse oder SIG_DFL / SIG_IGN |
| +8 | sa_flags | int64 | Kombination der SA_*-Flags |
| +16 | sa_restorer | int64 | 0 — Kernel nutzt vDSO-Restorer |
| +24 | sa_mask | int64 | Blockierte Signale während Handler |
| Konstante | Wert | Beschreibung |
SIGACTION_SIZE | 32 | Puffergröße in Bytes |
SA_NOCLDSTOP | 1 | Kein SIGCHLD bei Stopp von Kindprozessen |
SA_NOCLDWAIT | 2 | Kindprozesse werden nicht zu Zombies |
SA_SIGINFO | 4 | Handler erhält siginfo_t-Kontext |
SA_RESTART | 268435456 | Unterbrochene Syscalls automatisch neustarten |
SA_NODEFER | 1073741824 | Signal nicht während Handler blockieren |
SA_RESETHAND | 2147483648 | Handler nach erstem Aufruf auf SIG_DFL zurücksetzen |
Signal-Maske
Signalmasken-Konstanten im Überblick:
| Konstante | Wert | Beschreibung |
SIG_BLOCK | 0 | Signale zur Blockiermaske hinzufügen |
SIG_UNBLOCK | 1 | Signale aus Blockiermaske entfernen |
SIG_SETMASK | 2 | Blockiermaske vollständig ersetzen |
signalfd
| Konstante | Wert | Beschreibung |
SFD_CLOEXEC | 524288 | signalfd bei exec() schließen |
SFD_NONBLOCK | 2048 | signalfd nicht-blockierend |
SIGNALFD_SIGINFO_SIZE | 128 | Größe eines signalfd_siginfo-Eintrags |
Funktionen
Handler registrieren
| Signatur | Beschreibung |
SignalSet(signum: int64, handler: int64): int64 | Registriert handler für signum. handler ist eine Lyx-Funktion fn(signo: int64), SIG_DFL oder SIG_IGN. Echte Handler erhalten automatisch SA_RESTART |
SignalIgnore(signum: int64): int64 | Setzt den Handler auf SIG_IGN — Signal wird dauerhaft ignoriert |
SignalDefault(signum: int64): int64 | Stellt das Standard-Verhalten wieder her (SIG_DFL) |
Signal-Maske
Signalmasken-Konstanten im Überblick:
| Signatur | Beschreibung |
SignalMaskBlock(signum: int64): int64 | Fügt signum zur Blockiermaske hinzu — Signal wird zurückgehalten bis entsperrt |
SignalMaskUnblock(signum: int64): int64 | Entfernt signum aus der Blockiermaske |
SignalMaskGet(outMask: int64): int64 | Schreibt die aktuelle Blockiermaske in outMask (alloc(8)) |
Signal senden
| Signatur | Beschreibung |
SignalSend(pid: int64, signum: int64): int64 | Sendet signum an Prozess pid. pid=0 → eigene Prozessgruppe, pid=-1 → alle erreichbaren Prozesse |
SignalSendSelf(signum: int64): int64 | Sendet signum an den eigenen Prozess |
SignalSendThread(tgid: int64, tid: int64, signum: int64): int64 | Sendet signum an einen spezifischen Thread (tgkill) |
signalfd — Signal als fd empfangen
| Signatur | Beschreibung |
SignalFd(signum: int64): int64 | Erstellt einen signalfd für signum mit SFD_CLOEXEC. Signal muss vorher via SignalMaskBlock blockiert werden |
SignalFdRead(fd: int64, buf: int64): int64 | Liest ein signalfd_siginfo-Struct vom fd. buf: alloc(SIGNALFD_SIGINFO_SIZE). Gibt 128 bei Erfolg zurück |
SignalFdSigno(buf: int64): int64 | Extrahiert die Signalnummer aus einem gelesenen signalfd_siginfo-Puffer |
Verwendung
SIGTERM sauber abfangen
import std.signals;
import std.io;
var gRunning: bool := true;
fn OnTerminate(signo: int64): void {
PrintLn("SIGTERM empfangen, beende...");
gRunning := false;
}
fn Main(): void {
SignalSet(SIGTERM, OnTerminate as int64);
SignalSet(SIGINT, OnTerminate as int64);
while (gRunning) {
// Hauptschleife...
}
}
SIGPIPE ignorieren (Netzwerk-Server)
import std.signals;
fn InitServer(): void {
// Verhindert Prozessabbruch bei Schreiben in geschlossene Verbindung.
SignalIgnore(SIGPIPE);
}
signalfd mit epoll kombinieren
import std.signals;
import std.net.epoll;
import std.alloc;
import std.io;
fn RunWithSignalFd(): void {
// Signal blockieren, bevor signalfd erstellt wird!
SignalMaskBlock(SIGTERM);
SignalMaskBlock(SIGINT);
var sfd := SignalFd(SIGTERM);
// Zweiten signalfd für SIGINT erstellen, oder beide in eine Maske packen
// (hier vereinfacht: nur SIGTERM)
var ep := EpollCreate();
EpollAdd(ep, sfd, EPOLLIN, sfd);
var evBuf: int64 := alloc(EPOLL_EVENT_SIZE);
var sigBuf: int64 := alloc(SIGNALFD_SIGINFO_SIZE);
var n := EpollWait(ep, evBuf, 1, -1);
if (n > 0) {
SignalFdRead(sfd, sigBuf);
var signo := SignalFdSigno(sigBuf);
PrintLn("Signal empfangen: " + IntToStr(signo));
}
free(evBuf, EPOLL_EVENT_SIZE);
free(sigBuf, SIGNALFD_SIGINFO_SIZE);
close(sfd);
close(ep);
}
Signal an Kindprozess senden
import std.signals;
import std.process;
fn StopChild(childPid: int64): void {
SignalSend(childPid, SIGTERM);
}
Hinweise
SIGKILL und SIGSTOP können nicht abgefangen, ignoriert oder blockiert werden.
Für SignalFd muss das Signal vorher via SignalMaskBlock blockiert werden, sonst kann es vor dem SignalFdRead ausgeliefert werden.
SignalSet setzt automatisch SA_RESTART für echte Handler — unterbrochene Syscalls werden neu gestartet.
Der Kernel-vDSO-Restorer wird genutzt — kein eigener Trampolin-Code nötig.
Ein signalfd-fd lässt sich zusammen mit Netzwerk-fds und inotify-fds in dieselbe epoll-Instanz einhängen.
Verwandte Units
-
-
-
std.mqueue — POSIX Message Queues als IPC-Alternative
std.thread — Threads (Signal-Maske gilt pro Thread)
Letzte Aktualisierung: 2026-06-05