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

Letzte Aktualisierung: 2026-06-05