Horus107 schrieb:
I'm developing a scientific application that can be used standalone as well
as a library.
We use connection files to exchange information about socket based
connection. Upon an unclean exit these connection linger around, causing
trouble on the next startup.
I implemented a signal handler to clean up on unclean exit:
signal(SIGSEGV, precice::utils::terminationSignalHandler);
signal(SIGABRT, precice::utils::terminationSignalHandler);
signal(SIGTERM, precice::utils::terminationSignalHandler);
signal(SIGINT, precice::utils::terminationSignalHandler);
void terminationSignalHandler(int signal) {
// use boost filesystem to clean up
}
Falls es machbar ist, bietet es sich übrigens eher an, dass der Handler selber keine Ressourcen freigibt, sondern einfach ein Flag setzt, dass vom Hauptprogramm regelmäßig überprüft wird und dann gegebenenfalls ein normales Programmende über die normalen Freigabepfade ausgelöst wird.
Und im Falle einer Bibliothek ist es auf keinen Fall deine Aufgabe, Signalhandler zu erstellen. Du stellst Funktionen zur Freigabe der von der Bibliothek genutzten Ressourcen bereit, der Anwender der Bibliothek ist verantwortlich, dass diese auch korrekt aufgerufen werden.
Außerdem ist die signal-Funktion selbst böse und sollte nicht benutzt werden.
Manpage zu signal schrieb:
Avoid its use: use sigaction(2) instead.
Can I assume the application to be in a condition to actually do
something when these signals are called? I have doubts especially about
SIGSEGV regarding corruption of internal data structures.
Das kommt drauf an . Siehe den Abschnitt über das Unterbrechen von Systemcalls und -funktionen in der Manpage zur Signalbehandlung. Wie du siehst, zählen die ganzen socket-Funktionen zu denen, an die man hier gesondert gedacht hat. Du kannst also davon ausgehen, dass deine socket-Ressourcen in einem definierten Zustand sind, außer die genannten Ausnahmen greifen.
Can multiple signal handler be installed for one signal? Or do subsequent
invocations of signal(...) overwrite the handler for the resp. signal? If we
are used as a library and host application has installed own signal handler,
how can we omit overwriting them?
Nein, es kann nur einen Handler pro Signal geben. Der letzte gesetzte Handler für ein Signal ist der aktuell gültige.
Wie gesagt, sollte eine Bibliothek niemals Signale setzen.
If there are multiple handler for one signal, can we remove our handler
from the chain and re-emit the signal? Or should be just use std::exit or
std::abort?
Siehe oben.
Is this the right way to go for the problem described? Any comments
welcome!
Das hätte vielleicht die erste Frage sein sollen . Auf Anwendungsebene ist es durchaus richtig, Signalhandler zu benutzen, um das korrekte Freigeben von Ressourcen dieser Art zu gewährleisten (siehe aber mein Kommentar, dass der Handler selbst nicht der Freigeber sein sollte). Auf Bibliotheksebene, wie erklärt, nicht.
Denk da dran, dass durchaus noch andere Abbruchpfade existieren können. Ich weiß nicht, welche Sprache du benutzt, daher sind konkrete Tipps schwierig. In C++ müsstest du beispielsweise aufpassen, dass die Laufzeitumgebung auch ein terminate auslösen kann, welches die normale Ressourcenverwaltung in C++ aushebelt und daher auch mit einem entsprechenden Handler behandelt werden sollte (dafür ist natürlich die normale Ressourcenverwaltung in C++ wesentlich angenehmer :p ). In allen Sprachen gibt es natürlich auch Signale, die nicht auffangbar sind, deine Infrastruktur sollte also im Notfall auch mit dem Fall zurecht kommen, dass eine Ressource mal nicht freigegeben wird.