====== 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.
→ [[lyx_-_programmiersprache:units|Standard Library]] · [[lyx_-_programmiersprache:units:process|std.process]] · [[lyx_-_programmiersprache:units:net:epoll|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 =====
* ''[[lyx_-_programmiersprache:units:process|std.process]]'' — fork, exec, waitpid
* ''[[lyx_-_programmiersprache:units:process_ext|std.process_ext]]'' — UID/GID, Sessions, uname
* ''[[lyx_-_programmiersprache:units:net:epoll|std.net.epoll]]'' — epoll für signalfd-Integration
* ''[[lyx_-_programmiersprache:units:mqueue|std.mqueue]]'' — POSIX Message Queues als IPC-Alternative
* ''[[lyx_-_programmiersprache:units:thread|std.thread]]'' — Threads (Signal-Maske gilt pro Thread)
Letzte Aktualisierung: 2026-06-05