Dienst bei Herunterfahren sauber beenden


#1

Ich habe ein Programm, das als Dienst im Hintergrund läuft. Wenn der Rechner herunterfährt, will ich ihn sauber beenden können.

Ich habe das Signalhandling noch dunkel von Perl in Erinnerung (SIGTERM, SIGINT) und habe auch schon viel herum gegoogelt. Das oft empfohlene Vorgehen mit einem Shutdown-Hool

public class TestShutdownHook {

    public static void main(final String[] args) throws InterruptedException {
        Runtime.getRuntime().addShutdownHook(new Thread() {
            @Override
            public void run() {
                System.out.println("Shutdown hook!");
            }
        });

        while (true) {
            Thread.sleep(1000);
        }
    }

}

gibt zumindest beim Abbruch über den Taskmanager (Prozess beenden oder Prozesstruktur beenden) leider nichts aus. Mag es nun an Windows liegen oder woran auch immer, ich habe es aus Eclipse heraus wie auch aus einer Jar probiert, in beiden Fällen wurde nichts ausgegeben.

Quelle:


#2

In den Javadocs zu addShutdownHook steht noch folgendes:

In rare circumstances the virtual machine may abort, that is, stop running without shutting down cleanly. This occurs when the virtual machine is terminated externally, for example with the SIGKILL signal on Unix or the TerminateProcess call on Microsoft Windows.

In einem anderen Java-Forum gab es auch mal einen Thread dazu, der sich allerdings eher auf die Spezifika von Linux bezog, mit dem Ergebnis, dass eben manche Signale direkt die VM abwürgen und dann eben nichts mehr passiert.


#3

Ich habe keine Ahnung in wie weit Windows da noch POSIX kompatibel sein muss (früher war es so, um Staatliche Aufträge zu bekommen). Es kann auch sein das Windows an der Stelle ine anderes Signal sendet. Ich vermute aber das Du an der Stelle um die Windows-API herum kommst -> https://msdn.microsoft.com/de-de/library/windows/desktop/aa376889(v=vs.85).aspx


#4

Ich weiß nicht, wie es unter anderen Betriebssystemen aussieht, aber unter Windows muss man sich afaik gar keine Gedanken um saubere Beendigungen von Prozessen machen, weil der Prozessmanager zu jedem Prozess Listen führt, in welchem zugewiesener Speicher und beanspruchte Hardware abgelegt werden. Wenn ein Prozess plötzlich verschwindet oder durch SIGKILL abgewürgt wurde, erledigt Windows die restlichen Aufräumarbeiten, indem es die in der Liste geführten Ressourcen frei gibt. Ich jedenfalls mache mir um saubere Beendigung von Programmen - also ShutdownHooks - nur dann noch Gedanken, wenn Exceptions einen Neustart erfordern.
Klar, dass solche automatischen Neustarts bei einem Reeboot nicht willkommen sind, warum sollte man ihm also eine solche Gelegenheit geben?
Nicht nur in Java sorgt so ziemlich jeder ShutdownHook möglicherweise für das Abdunkeln des Bildschirms vor dem Reboot mit der Option: “Neustart erzwingen”.


#5

Danke euch dreien schonmal.

@ionutbaiu Ja das hatte ich auch gelesen, das kann hier natürlich gut der Fall sein.
@mogel: Das les ich mir mal durch
@Spacerat: Hier war eher das Problem, dass gar nichts passiert.


#6

Im Java-Blog-Buch, das ursprünglich von Stefan Kiesel initiiert und geführt wurde und nun zu byte-welt gehört, kann man einen Artikel dazu finden: https://www.java-blog-buch.de/d-code-beim-beenden-ausfuhren-jdk-13/


#7

Saubere Sache, dieser Blog.

Allerdings vermisse ich dort auch den Umstand, dass Betriebssysteme nicht dazu verpflichtet sind, Programme sauber zu beenden und dies möglicherweise deswegen auch gar nicht tun - also das Problem verursachen, dass gar nichts passiert.


#8

ShutDownHooks sind selten das Mittel der Wahl fuer sowas (oder eigentlich alles :wink: ), es gibt zuviele Unwaegbarkeiten, IMHO sind ShutDownHooks “broken by Design”, weil u.a. beim Shutdown gar nciht ausgefuehrt werden, hat man mehrere gehen die Probleme richtig los (welche Reihenfolge? Gibt es die Ressourcen noch die geschlossen werden sollen? etc. pp.)

Welche Ressource willst du den “sauber beenden” bzw. freigeben?

Wenn du eigene Threads gestartet hat, dann nicht als “Daemon” und richtig(!) auf InterruptedExceptions reagieren ist meist der bessere Weg. Falsches behandeln von InterruptedExceptions fuehrt u.U. dazu, dass der Rechner beim Runterfahren ein paar Minuten haengt (Timeout).