Programm von extern beenden
-
Hi
Ich habe eine Fraktalgenerator für die Kommandozeile erstellt, der im Hintergrund Fraktale berechnet. Das Programm läuft unter Linux und W2k, an den entspr. Stellen checke ich mit #ifdef, für welche Pattform kompiliert wird.
Um auf das Beenden den Programms zu reagieren, habe ich Standard-Signalhandler verwendet (signal(...), wobei ich SINTERM und SIGINT verarbeite). Das Abbrechen mit Strg+C funktioniert auch problemlos, unter Linux auch SIGTERM (Kill-Befehl).
Nun habe ich bereits (mit Delphi5) ein Kontrollprogramm entwickelt, um einen seti-Client zeitgesteuer zu starten und beenden. Hier wird das Programm mit der API-Funktion TerminateProcess bei bedarf beendet. Das möchte ich jetzt auch für mein Fraktalprogramm übernehmen. Das Problem ist aber, daß Terminate-Process meinen Prozess sofort beendet, ohne daß irgendein Signalhandler noch vorher greifen kann.
Gibt es
a) eine Alternative zu TerminateProcess, die es meiner Anwendung noch erlaubt, auf die Beendigung zu reagieren und Daten zu speichern ?
b) Ich kann TerminateProcess einen Exitcode mitgeben. Welchen muß ich nehmen, um in meiner Anwendung SIGINT/SIGTERM auszulösen (sofern das überhaupt geht)?Da ich mein Programm aus einem Quelltext für Windoof und Linux kompilieren möchte, suche ich erst einmal nach einer einfachen, möglichst Ansi-C genormten Methode. Nur im äußerten Notfall möchte ich Windoof-sprzifische Funktionen (wie threads, Windows-Messagesverarbeitung o.ä. verwenden).
Jürgen
-
Ich hab zwar noch keine Programme für Linux erstellt, aber TerminateProcess() ist ja schon eine spezifische Funktion aus dem Win32 API.
zu b)
Ehrlich gesagt kann ich nichts finden, das daraufhin deutet, dass der ExitCode in irgendeiner direkten Beziehung zur Ausführung eines Interrupt Signals, gesetzt mit signal(), steht. Ist auch relativ unwahrscheinlich, da TerminateProcess() zur Windows API und signal() zur StdLib (ANSI C) gehört.
Man kann zwar den ExitCode abfragen (und entsprechend auswerten), aber das bringt wohl nur was (sofern möglich), wenn man sein Programm über den Windows Message Loop (PeekMessage(), GetMessage(), etc.) aufbaut. Aber vielleicht kann mir ja mal jemand erklären, wozu der ExitCode überhaupt gut sein soll und wo man den verwenden kann.zu a)
Entsprechend meinen Angaben zu b) kann der Ansatz für die Lösung deines Problems eigentlich nur hier zu finden sein.
Nochmal zum Verständnis: Du hast also ein Programm (Kontrollprogramm war das mit Delphi Absicht ), welches andere Programme startet bzw. beendet (zeitgesteuert). Dein Problem liegt im Grunde darin, einem solchen anderen Programm (Fraktalgenerator) mitzuteilen, dass es jetzt beendet wird und möglichst vorher noch alle wichtigen Dinge erledigen soll (zB aufs Klo gehen).Dafür kann man folgende zwei Lösungsansätze betrachten:
Ich nenn der Einfachheit halber
Kontrollprogramm S (Server) und
Fraktalgenerator-Programm C (Client)
1. S teilt C mit, dass C beendet wird -> S wartet bis C zur Beendigung bereit
C erkennt Beendigung -> ...things to do...
C teilt S mit, dass C zur Beendigung bereit
S beendet C
Auf diesem Gleis bewegst du dich momentan.
Dieser Signalaustausch basiert auf dem Client-Server-Prinzip und ist aufwendiger zu realisieren. Er hat allerdings den Vorteil, dass die völlige Kontrolle (Starten/Beenden eines Programms) beim Server liegt.
2. S teilt C mit, dass C beendet wird
C erkennt Beendigung -> ...things to do...
C beendet sich
Dieser Ansatz ist wesentlich einfacher zu realiseren.
Da C sich irgendwann eh beenden sollte (Programmhauptschleife main() wird beendet) sollte man dafür sorgen, dass genau dies passiert sobald C die Beendigung erkennt.
Das einzigste Problem was jetzt noch bleibt, ist wie teilt S die Beendigung C mit. Da mir momentan keine ANSI C Lösung einfällt, kann ich dir nur den Tipp geben es über das Nachrichten- Handling der Windows API zu probieren (eigentlich genau das was du wolltest ). Allerdings muss das für Linux dann ebenfalls gemacht werden.Eine weitere Möglichkeit besteht darin, weiterhin mit TerminateProcess() das Programm zu beenden und in diesem Programm mit der Funktion atexit() eine Funktion zu definieren, welche am Ende ausgeführt wird. Ob dies allerdings funktioniert kann ich dir nicht sagen (Windows API <-> StdLib naja hatten wir ja schon mal).
Ich hoffe ich hab verstanden was du willst und liege nicht total daneben.
-
Hi
Die jetzige Realisieung entspr. eher deiner Version 2. ZZ. kontrolliert mein Programm einen Seti-Textclient. Wenn der Zeipunkt zum Beenden kommt, wird dieser einfach per Terminateprocess gekillt. Datenverlust tritt praktisch keiner auf,da der Client jede Minute seine Daten speichert.
Daß das Kontrollprogramm in Delphi ist, war volle Absicht. Wir arbeiten primär mit Delphi, der CBuilder (V3.0) war eine Zugabe zu unserer Delphi-Version.
Das Einbinden von atexit funktioniert nicht, mit Terminateprocess wird auch das nicht mehr ausgeführt, mit Strg+C-Abbruch ist es ok.
Das Problem ist jetzt nach wie vor, wie kann ich dem Client die Beendigung mitteilen. Mit den Windoof-Messageloops kenne ich mich so gut wie garnicht aus. Der Client ist ein Textmode-Programm und von einem früheren Delphi-Textmode-Projekt weiß ich, daß es hier anscheinend nicht so einfach geht, die Messages abzufragen.
Nach wie vor wümscheich mir eine einfache Lösung wie unter Linux, aber anscheined geht das nicht.
Jürgen