Ich habe ein Programm, das bestimmte Aufgaben ausführen muss, bevor es beendet wird. Das Problem ist, dass manchmal das Programm mit einer Ausnahme abstürzt (wie die Datenbank nicht erreichbar ist, usw.). Gibt es nun eine Möglichkeit, eine abnormale Beendigung zu erkennen und Code auszuführen, bevor er stirbt?
Danke.
Code wird geschätzt.
1. Win32
Die Win32-API enthält eine Möglichkeit, dies über den SetUnhandledExceptionFilter zu tun funktionieren wie folgt:
%Vor%2. POSIX / Linux
Normalerweise mache ich das über die Funktion signal () und handle dann entsprechend mit dem SIGSEGV-Signal. Sie können auch das SIGTERM-Signal und SIGINT verarbeiten, aber nicht SIGKILL (von Entwurf). Sie können strace () verwenden, um ein Backtrace zu erhalten, um zu sehen, was das Signal verursacht hat.
Es gibt sysinternals Forum-Threads zum Schutz vor End-Prozess-Versuchen durch das Anhängen von NT Interna, aber was Sie wirklich wollen, ist entweder ein Watchdog oder Peer-Prozess (vernünftiger Ansatz) oder eine Methode zum Abfangen von katastrophalen Ereignissen (ziemlich heikel).
Bearbeiten: Es gibt Gründe, warum sie dies schwierig machen, aber es ist möglich, Versuche, Ihren Prozess zu beenden, abzufangen oder zu blockieren. Ich weiß, du versuchst nur aufzuräumen, bevor du gehst, aber sobald jemand einen Prozess freigibt, der nicht sofort getötet werden kann, wird jemand nach einer Methode fragen, um ihn sofort zu töten, und so weiter. Jedenfalls, um diesen Weg zu gehen, siehe oben verlinkten Thread und suchen Sie einige Schlüsselwörter, die Sie dort für mehr finden. hook ODER filter NtTerminateProcess usw. Wir reden hier über Kernel-Code, Gerätetreiber, Antivirus, Sicherheit, Malware, Rootkit-Zeug. Einige Bücher, die in diesem Bereich helfen, sind native Windows NT / 2000-API , Undokumentierte Windows 2000-Geheimnisse: Ein Programmierer-Kochbuch , Rootkits: Untergraben des Windows-Kernels und natürlich Windows® Internals: Fünfte Ausgabe . Dieses Zeug ist nicht zu schwer zu kodieren, aber ziemlich empfindlich, um genau richtig zu werden, und Sie könnten unerwartete Nebenwirkungen einführen.
Vielleicht könnte Funktionen für die Wiederherstellung und das Neustarten von Anwendungen nützlich sein? Unterstützt von Vista und Server 2008 und höher.
ApplicationRecoveryCallback-Callback-Funktion Anwendungsdefinierte Callback-Funktion zum Speichern von Daten und Anwendungsstatusinformationen für den Fall, dass die Anwendung auf eine nicht behandelte Ausnahme stößt oder nicht mehr reagiert.
Wenn Sie SetUnhandledExceptionFilter verwenden, MSDN Social Diskussion empfiehlt, dass, um diese Arbeit zuverlässig zu machen, das Patchen dieser In-Memory-Methode die einzige Möglichkeit ist, sicher zu sein, dass Ihr Filter aufgerufen wird. Berät stattdessen, dass stattdessen __try / __ umbrochen wird. Ungeachtet dessen gibt es in dem Artikel "SetUnhandledExceptionFilter" und VC8 einen Beispielcode und eine Diskussion über das Filtern von Aufrufen von SetUnhandledExceptionFilter.
Siehe auch Windows SEH Revisited im The Awesome Factor für ein Beispiel Code von AddVectoredExceptionHandler .
Es hängt davon ab, was Sie mit Ihren "Ausnahmen" machen. Wenn Sie sie richtig handhaben und das Programm verlassen, können Sie Ihre Funktion beim Beenden mit atexit()
registrieren.
Es funktioniert nicht im Falle einer echten abnormalen Beendigung wie segfault.
Ich weiß nichts über Windows, aber auf POSIX-konformen Betriebssystemen können Sie Signal-Handler installieren, die verschiedene Signale empfangen und etwas dagegen tun. Natürlich können Sie SIGKILL
und SIGSTOP
nicht abfangen.
Die Signal-API ist seit C89 Teil von ANSI C und wird wahrscheinlich von Windows unterstützt. Siehe signal()
syscall für Details.
Wenn es nur Windows gibt, können Sie SEH verwenden ( SetUnhandledExceptionFilter ) oder VEH ( AddVectoredExceptionHandler , aber nur für XP / 2003 und älter)
Erstens, obwohl dies ziemlich offensichtlich ist: Sie können niemals eine völlig robuste Lösung haben - jemand kann immer nur das Stromkabel drücken, um Ihren Prozess zu beenden. Sie brauchen also einen Kompromiss, und Sie müssen die Details dieses Kompromisses sorgfältig auslegen.
Eine der robusteren Lösungen besteht darin, den entsprechenden Code in ein Wrapper-Programm zu schreiben. Das Wrapper-Programm ruft Ihr "echtes" Programm auf, wartet darauf, dass sein Prozess beendet wird, und führt dann - sofern Ihr "echtes" Programm nicht anzeigt, dass es normal beendet wurde - den Bereinigungscode aus. Dies ist ziemlich üblich für Dinge wie Testkabelbäume, bei denen das Testprogramm wahrscheinlich abstürzt oder abbricht oder anderweitig auf unerwartete Weise stirbt.
Das gibt Ihnen immer noch die Schwierigkeit, was passiert, wenn jemand einen TerminateProcess für Ihre Wrapper-Funktion ausführt, wenn Sie sich darüber Gedanken machen müssen. Bei Bedarf können Sie dies umgehen, indem Sie es als Dienst in Windows einrichten und die Betriebssystemfunktionen verwenden, um es neu zu starten, falls es abstürzt. (Dies ändert die Dinge nur ein wenig; jemand könnte den Dienst einfach anhalten.) An diesem Punkt sind Sie wahrscheinlich an einem Punkt, an dem Sie eine erfolgreiche Beendigung durch etwas Persistentes wie das Erstellen einer Datei signalisieren müssen.
Ich habe vor einigen Jahren einen Artikel auf ddj.com über "post mortem debugging" veröffentlicht.
Es enthält Quellen für Windows und Unix / Linux, um eine abnormale Beendigung zu erkennen. Nach meiner Erfahrung ist ein Windows-Handler, der mit SetUnhandledExceptionFilter installiert wurde, nicht immer aufgerufen. In vielen Fällen wird es aufgerufen, aber ich erhalte ziemlich viele Protokolldateien von Kunden, die keinen Bericht von den installierten Handlern enthalten, wo ein ZUGRIFFSVERSTOSS die Ursache war.
Tags und Links c windows process termination