best practice bei Signalen

10/04/2009 - 13:02 von Markus Wichmann | Report spam
Hi all,

ich habe schon bei Google nach allem Möglichen gesucht, aber ich habe
nix richtiges gefunden: Wie soll sich eine Anwendung bei Signalen
verhalten, die es nicht kennt?

Hintergrund ist, dass ich gerade bei audacious bemerkt habe, dass es
zusammenbricht, wenn es ein SIGHUP abbekommt. Dabei ist ein SIGHUP doch
für audacious ungefàhrlich, schließlich ist es eine X11-Anwendung und
als solche in ihrer Funktion nicht von einem Terminal abhàngig.

Nun habe ich mir mal den Quelltext von audacious angesehen und fragte
mich, ob so eine Implementierung nicht eigentlich in die Schublade
"Herr, vergib ihnen, denn sie wissen nicht, was sie tun!" gehört:
Audacious hat sich einen eigenen Signlhandler gebastelt: Man nehme

- einen eigenen Thread
- ein sigset, in das nur rein kommt, welche Signale behandelt werden
sollen
- eine Endlosschleife
- sigwait()
- und ein switch/case

Also richtig ekelhaft. Nun wollte ich wissen, ob das irgendwelche
Vorteile gegenüber der guten alten Registrierung von Signalhandlern
mittels signal() oder sigaction() hat.

Aber BTT: Wie soll sich eine Anwendung uninteressanten Signalen
gegenüber verhalten? Ignorieren klingt gut, aber wie geht das halbwegs
portabel? Ich meine, C99 definiert ein paar wenige Signale, SUSv3 schon
wesentlich mehr und beide Standards lassen noch
implementierungsabhàngige Signale zu. Spontan klingt da die Geschichte
mit sigset_t nicht schlecht, weil es dafür die Funktion sigfillset()
gibt, die wirklich _alle_ Signale erfasst. Ich dachte jetzt an
folgendes:

- ein sigset_t erstellen, in dem alle Signale drinstehen, die mich nicht
ineressieren
- diese Signale ignorieren

Nur fehlt leider irgendwie das Mittelstück: Es gibt keine Funktion, die
alle Elemente eines sigset_t ignoriert. Ich kann die Signale nur
blockieren, was bedeutet, dass ich sie in eine Warteschlange stelle, die
im Laufe des Betriebes immer lànger wird. Außerdem gibt es ein paar
undefinierte Verhaltensweisen, wenn bestimmte Signale ankommen, wàhrend
sie blockiert sind.

Schlussendlich wàre also eine Möglichkeit gefragt, über wirklich alle
Signale, die die Platform bereitstellt, zu iterieren. Wenn das geht,
möglichst portabel, dann hàtte ich ein paar Probleme weniger. Es bleibt
die Frage, ob es überhaupt gut ist, diese Signale einfach zu ignorieren.
Oder gibt es ein paar Signale, die man immer behandeln sollte, oder so?

Tschö,
Markus

GUI - ein Hintergrundbild und zwölf XTerms

vim -c "exec \"norm iwHFG#NABGURE#IVZ#UNPXRE\"|%s/#/ /g|norm g??g~~"
 

Lesen sie die antworten

#1 Rainer Weikusat
11/04/2009 - 11:54 | Warnen spam
Markus Wichmann writes:
Hintergrund ist, dass ich gerade bei audacious bemerkt habe, dass es
zusammenbricht, wenn es ein SIGHUP abbekommt. Dabei ist ein SIGHUP doch
für audacious ungefàhrlich, schließlich ist es eine X11-Anwendung und
als solche in ihrer Funktion nicht von einem Terminal abhàngig.



Ein 'hangup'-Signal dient dazu, noch laufende (interaktive) Prozesse
zu beenden, nachdem die login-session eines Benutzers aus irgendeinem
Grund beendet wurde (urspruenglich wohl tatsaechlich durch 'Auflegen'
einer Modemverbindung). Das betrifft grundsaetzlich auch graphische
Anwendungen.

Nun habe ich mir mal den Quelltext von audacious angesehen und fragte
mich, ob so eine Implementierung nicht eigentlich in die Schublade
"Herr, vergib ihnen, denn sie wissen nicht, was sie tun!" gehört:
Audacious hat sich einen eigenen Signlhandler gebastelt: Man nehme

- einen eigenen Thread
- ein sigset, in das nur rein kommt, welche Signale behandelt werden
sollen
- eine Endlosschleife
- sigwait()
- und ein switch/case

Also richtig ekelhaft.



Zufaelligerweise ist das eigentlich das 'empfohlene' Verfahren um mit
Signalen in Anwendungen mit mehreren threads umzugehen. Statt einem
switch-Statement (das gcc unter der Annahme, die einzelnen Faelle
traeten mit gleicher Haeufigkeit auf, zu sonstwas uebersetzen wird)
wuerde ich ein durch die Signalnummer indiziertes Funktionszeigerfeld
benutzen, aber im wesentlichen wird 'Signalbehandlung durch einen
dedizierten thread' immer so aussehen, wie Du es oben beschrieben
hast.

Nun wollte ich wissen, ob das irgendwelche
Vorteile gegenüber der guten alten Registrierung von Signalhandlern
mittels signal() oder sigaction() hat.



Es fuehrt dazu, dass alle Signale von einem thread synchron
abgearbeitet werden anstatt von irgendwelchen threads asynchron, dh es
gibt keine Probleme mit gegebenenfalls 'zu einem ungeunstigen
Zeitpunkt' unterbrochenen API-Routinen.

Aber BTT: Wie soll sich eine Anwendung uninteressanten Signalen
gegenüber verhalten?



[...]

Ich dachte jetzt an folgendes:

- ein sigset_t erstellen, in dem alle Signale drinstehen, die mich nicht
ineressieren
- diese Signale ignorieren



Benutzer lieben Anwendungen, die sie deswegen nicht normal beenden
koennen, weil derjenige, der den Code geschrieben hat, der Ansicht
war, das sollte nicht moeglich sein. ZB gibt es eine Signal namens
SIGQUIT(3), das via Tastatur ausgeloest werden kann (C-\) und ein
Program beendet und einen coredump erzeugt. Woher willst Du wissen
wozu den jemand gebrauchen koennte, insbesondere, wenn man davon
ausgeht, das jeder Code irgendwelche Fehler enthaelt und mit einer
Menge von anderem Code, fuer den das auch gilt, interagiert?

Fuer 'unbekannte Signale' ist das noch irrsinniger, denn die Leute,
die ein solches Signal erfunden haben, insbesondere, wenn es ausserdem
noch per default einen Prozess beendet, werden auch der Ansicht
gewesen sein, dass es einen guten Grund fuer eine so gravierende
Aktion gab.

Nur fehlt leider irgendwie das Mittelstück: Es gibt keine Funktion, die
alle Elemente eines sigset_t ignoriert. Ich kann die Signale nur
blockieren, was bedeutet, dass ich sie in eine Warteschlange stelle, die
im Laufe des Betriebes immer lànger wird.



Normalerweise nicht. Sogenannte 'Echtzeitsignale' (realtime signals)
sollen in einen Warteschlange gestellt werden, aber 'normale Signale'
werden sich typischerweise als gesetztes Bit in einer Bitmaske
manifestieren, dh die sind entweder 'pending' oder 'nicht pending'.

Außerdem gibt es ein paar undefinierte Verhaltensweisen, wenn
bestimmte Signale ankommen, wàhrend
sie blockiert sind.



Du hattest nicht ernsthaft vor, SIGILL, SIGSEGV usf zu blockieren,
nein? Kann ja nicht sein, dass sie wirklich auf ein Problem
hindeuten. Wahrscheinlich alles bloss Idioten, diese Kernelentwickler
...

Ähnliche fragen