Geschichte der Frage:
Perl wurde als Sprache für systematische Skripte entwickelt, daher war die Signalverwaltung (SIGTERM, SIGINT, SIGHUP) immer eine eingebaute und leistungsstarke Funktion. Dieses System ermöglicht es, externe Ereignisse (Benutzereingaben zum Stoppen, Neustarten von Daemons, Zeitüberschreitungen) abzufangen und Skripte angemessen zu beenden oder ihr Verhalten zu ändern.
Problem:
Eine falsche Signalverarbeitung ist eine häufige Ursache für inkorrekte Beendigungen oder das Einfrieren von Skripten, Datenverluste bei einem notforceigen Beenden, und die Unmöglichkeit, Prozesse ohne Verlust des Status oder der Ressourcen neu zu starten.
Lösung:
Signale werden durch das Setzen von Handlern in einem speziellen Hash %SIG verarbeitet. Eine gute Praxis ist Minimalismus bei den Aktionen innerhalb des Signalhandlers (zum Beispiel, das Setzen eines Flags und sicheres Beenden im Hauptthread). Für korrektes Arbeiten in Threads und bei mehrfacher Signalverarbeitung werden spezialisierte Module verwendet (z.B. POSIX::sigaction).
Beispiel:
my $term = 0; $SIG{TERM} = sub { $term = 1; }; while (1) { last if $term; # Hauptarbeit } print "Graceful shutdown ";
Schlüsselpunkte:
Kann man print/IO innerhalb eines Signalhandlers verwenden?
Antwort: Nicht empfohlen — es wird zu inkorrekt funktionierenden Ergebnissen und möglichen Datenverlusten kommen! Der moderne Standard sieht minimalen Code vor (nur das Setzen von Flags/Leeren von Variablen).
Was passiert, wenn der Signalhandler nach dem ersten Auslösen nicht zurückgesetzt wird?
Antwort: Der Handler wird mehrmals ausgeführt, wenn das Signal erneut empfangen wird. Wenn eine Reaktion nur auf das erste Ereignis erforderlich ist, muss der Handler $SIG{...} selbst zurücksetzen oder sich selbst signalisieren.
Ist die Signalverarbeitung in Perl threadsicher?
Antwort: Nein! In mehrsträngigem Perl werden Signalhandler nur im Hauptthread (Hauptinterpreter) aufgerufen; innerhalb von Threads können Signale ganz ignoriert oder inkorrekt verarbeitet werden.
Ein Dämonprozess ruft beim Empfang von SIGTERM sofort einen Close auf allen Dateideskriptoren auf und entfernt temporäre Dateien im Handler — von Zeit zu Zeit werden Dateien nicht gelöscht, Daten gehen verloren.
Vorteile:
Nachteile:
Der SIGTERM-Signalhandler setzt nur die Variable $exit, wonach die Hauptschleife die Arbeit vorsichtig beenden, Dateien schließen und dann Ressourcen freigeben kann.
Vorteile:
Nachteile: