====== 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