How to prevent shutdown hook from getting deadlock?

1.1k views Asked by At

I've seen a question here asked by @Tej Kiran which is exactly my question but it is not answered, the last comment says:

"Do you know if there are any shutdown hooks registered in your application, or if any of the libraries you are using that has a shutdown hook? The shutdown hook is a thread, and if there is a deadlock in that thread causing it to never terminate, the JVM will never exit."

There is a method shutdown hook in my program

Runtime.getRuntime().addShutdownHook(new Thread("Shutdown Hook") {
    @Override
    public void run() {

        System.out.println("---------------");
        System.out.printf("%d threads running%n", Thread.activeCount());

        Map<Thread, StackTraceElement[]> threads = Thread
                .getAllStackTraces();
        for (Entry<Thread, StackTraceElement[]> e : threads.entrySet()) {
            Thread t = e.getKey();

            System.out.printf("%s\t%s\t%s%n", t.getName(),
                    t.isDaemon(), t.isAlive());

            StackTraceElement[] elements = e.getValue();

            for (StackTraceElement trc : elements) {
                System.out.println("\t" + trc);
            }
        }

        System.out.println("---------------");

        try {UIUtil.cancelAllTasks();} catch (Throwable e) {e.printStackTrace();};

        try {mehad.io.port.ScannerManager.disableAutoHandshake();} catch (Throwable e) {e.printStackTrace();};

        try {mehad.io.port.ComPortInterface.getInstance().close();} catch (Throwable e) {e.printStackTrace();};

        try {
            if (lockStream != null) {
                lockStream.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
});

But I don't know how to distinguish if there is a deadlock in my shutdown hook and if there is any, how to solve it.

2

There are 2 answers

0
AudioBubble On

My own answer:

you know it seems that it has nothing to do with shutdown hook! I'd used WindowListener to close the MainFrame, I added a condition if to show a message whether the user want to leave or not? and if the answer was yes it goes to System.exit(0). previously there wasn't the condition to ask before closing the window. And Now it works fine! even on some rare machines which didn't work before. But Still I don't know how it works fine with that line added! I would be grateful if anyone can explain how it works fine now!

     this.addWindowListener(new WindowAdapter() {
                    public void windowClosing(WindowEvent ev) {

                        try {
                            ComPortInterface.getInstance().close();
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
//this if condition is added to ask if you want to exit or not
                        if (MessageUtil.showYesNo("Exit ?")) {
                            System.exit(0);
                        }

                    //  System.exit(0);
                    }
                });
0
Alex On

For start - your ShutdownHook works fine. Now about deadlocks.

Do you know if there are any shutdown hooks registered in your application?

I'm pretty sure that there are no such things because if there is another deadlock in some third party part then your app would be locked even without your hook. I believe it's not the fact because you have complains about your code - so without your hook it works fine and so there is no third party hooks.

Your deadlock is in one of these calls:

try {UIUtil.cancelAllTasks();} catch (Throwable e) {e.printStackTrace();};

            try {mehad.io.port.ScannerManager.disableAutoHandshake();} catch (Throwable e) {e.printStackTrace();};

            try {mehad.io.port.ComPortInterface.getInstance().close();} catch (Throwable e) {e.printStackTrace();};

            try {
                if (lockStream != null) {
                    lockStream.close();
                }

Fact that they are wrapped into try/catch block doesn't prevent them of being deadlock.

There is no code provided about these methods. Even lockStream.close(); could lock your execution.

Remove them one my one and see what is causing your blocking. Then go inside and see what actually block them.