Frage

Wenn durch ein Wunder ein segfault in unserem Programm auftritt, mag ich die SIGSEGV fangen und lassen die Benutzer (möglicherweise ein GUI-Client) kennt, mit einem einzigen Rückgabecode, der ein ernsthaftes Problem aufgetreten ist. Zugleich würde Ich mag Informationen auf der Kommandozeile angezeigt werden zu zeigen, welches Signal gefangen wurde.

Heute ist unser Signal-Handler sieht wie folgt aus:

void catchSignal (int reason) {
  std :: cerr << "Caught a signal: " << reason << std::endl;
  exit (1);
}

kann ich die Schreie des Entsetzens mit der oben hören, wie ich aus diesem Thread , dass es böse ist, eine nicht-Reentry-Funktion von einem Signal-Handler aufrufen.

Gibt es eine tragbare Art und Weise das Signal und liefern Informationen für die Nutzer?

zu handhaben

EDIT:? Oder zumindest tragbar im POSIX Rahmen

War es hilfreich?

Lösung

Die Tabelle listet alle Funktionen, die POSIX-Garantien Asynchron-Signal sicher und so sein kann von einem Signal-Handler aufgerufen werden.

Durch die Verwendung des ‚Schreib‘ Befehl aus dieser Tabelle, die folgende relativ „hässlich“ Lösung hoffentlich den Trick:

#include <csignal>

#ifdef _WINDOWS_
#define _exit _Exit
#else
#include <unistd.h>
#endif

#define PRINT_SIGNAL(X) case X: \
          write (STDERR_FILENO, #X ")\n" , sizeof(#X ")\n")-1); \
          break;

void catchSignal (int reason) {
  char s[] = "Caught signal: (";
  write (STDERR_FILENO, s, sizeof(s) - 1);
  switch (reason)
  {
    // These are the handlers that we catch
    PRINT_SIGNAL(SIGUSR1);
    PRINT_SIGNAL(SIGHUP);
    PRINT_SIGNAL(SIGINT);
    PRINT_SIGNAL(SIGQUIT);
    PRINT_SIGNAL(SIGABRT);
    PRINT_SIGNAL(SIGILL);
    PRINT_SIGNAL(SIGFPE);
    PRINT_SIGNAL(SIGBUS);
    PRINT_SIGNAL(SIGSEGV);
    PRINT_SIGNAL(SIGTERM);
  }

  _Exit (1);  // 'exit' is not async-signal-safe
}

EDIT:. Aufbauend auf Fenster

Nach dem Versuch, diese ein Fenster zu bauen, scheint es, dass ‚STDERR_FILENO‘ ist nicht definiert. Aus der Dokumentation jedoch sein Wert erscheint ‚2‘ zu sein.

#include <io.h>
#define STDIO_FILENO 2

EDIT: 'exit' soll nicht von den Signal-Handler entweder aufgerufen werden

Wie von fizzer wies darauf hin, ist _Exit in dem obigen Aufruf ein Vorschlaghammer Ansatz für Signale wie HUP und TERM. Im Idealfall, wenn diese Signale kann gefangen werden einen Flag mit „volatilen sig_atomic_t“ Typ verwendet werden, um das Hauptprogramm zu informieren, dass es sollte verlassen.

Im Folgenden Ich fand nützlich in meiner Suche.

  1. Einführung in Unix-Signale Programmierung
  2. Erweiterung Traditionelle Signale

Andere Tipps

FWIW, 2 Standardfehler unter Windows auch, aber Sie werden einige bedingte Kompilierung müssen, weil ihre write () _write () aufgerufen wird. Sie werden auch wollen

#ifdef SIGUSR1 /* or whatever */

etc um alle Verweise auf Signale nicht garantiert durch den C-Standard definiert werden.

Auch, wie oben erwähnt, wollen Sie nicht SIGUSR1, SIGHUP, SIGINT, SIGQUIT und SIGTERM wie diese behandeln.

Richard, immer noch nicht genug Karma zu kommentieren, so dass eine neue Antwort, die ich Angst habe. Dies sind asynchrone Signale; Sie haben keine Ahnung, wenn sie geliefert werden, so möglicherweise werden Sie in der Bibliothek Code sein, der konsistent zu bleiben informiert zu sein. Signal-Handler für diese Signale sind daher zurück erforderlich. Wenn Sie exit () aufrufen, tun die Bibliothek einige Arbeit post-main (), einschließlich Funktionen registriert mit atexit () aufrufen und die Standard-Streams aufzuräumen. Diese Verarbeitung kann fehlschlagen, wenn, sagen wir, das Signal in einer Standard-Bibliothek I / O-Funktion angekommen. Daher in C90 Sie sind nicht erlaubt Ausgang () aufrufen. Ich sehe jetzt, C99 die Anforderung entspannt durch eine neue Funktion _Exit () in stdlib.h bietet. _Exit () kann sicher von einem Handler für ein asynchrones Signal bezeichnet werden. _Exit () nicht aufrufen atexit () Funktionen und weglassen können die Standard-Streams bei der Umsetzung des Ermessens aufzuräumen.

Um bk1e (Kommentator ein paar Beiträge oben) Die Tatsache, dass SIGSEGV synchron ist, warum Sie nicht Funktionen verwenden können, die nicht einspringenden sein sollen. Was passiert, wenn die Funktion, die eine Sperre abgestürzt hielt, und die Funktion durch die Signal-Handler aufgerufen versucht, den gleichen Lock zu erwerben?

Dies ist eine Möglichkeit, aber es ist nicht ‚die Tatsache, dass SIGSEGV synchron ist‘, was das Problem ist. Aufruf nichtablaufinvarianten Funktionen aus dem Handler ist viel schlimmer mit asynchronen Signalen aus zwei Gründen:

  • asynchrones Signal-Handler sind (In der Regel) in der Hoffnung zurückzukehren und Fortsetzung der normalen Programmausführung. EIN Behandlungsroutine für ein synchrones Signal ist, (In der Regel) gehen zu beenden wie auch immer, so haben Sie nicht viel verloren, wenn Sie abstürzen.
  • in einem perversen Sinn, Sie haben die absolute Kontrolle über, wenn ein Synchronsignal geliefert wird - es passiert, wie Sie Ihren defekten Code ausführen, und zu keiner anderen Zeit. Sie haben keine Kontrolle überhaupt über, wenn ein asynchrones Signal geliefert wird. Es sei denn, die eigene E / A-Code des OP ist Blattes selber die Ursache des Mangels - z.B. Ausgeben ein schlechtes Zeichen. * - seine Fehlermeldung auf Erfolg eine vernünftige Chance hat

ein Launcher-Programm Schreiben Sie Programm auszuführen und abnormal Exit-Code an den Benutzer melden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top