numeric
numeric

Reputation: 485

How can I "capture" System.exit(-1) from different thread?

I have the following

System.setSecurityManager(new SecurityManager() {
    @Override
    public void checkExit(int status) {
        super.checkExit(status);

        //custom exception extends SecurityException
        throw new SystemExitCalledException();
    }
});

Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
    @Override
    public void uncaughtException(Thread t, Throwable e) {
        //never reaches here somehow... 
        //maybe some3rdPartyStaticMethod sets this, too?
    }

});


try {
    //this method spawns threads and some call System.exit().
    some3rdPartyStaticMethod.invoke(null, new Object[]{args});
} catch (SystemExitCalledException e) {
    //it never reaches here because 
    //SystemExitCalledException is thrown on different thread?? 
    //
}

Is there a way to prevent some3rdPartyStaticMethod's spawned thread's System.exit() call from halting jvm?

Upvotes: 1

Views: 1123

Answers (2)

Mark Byers
Mark Byers

Reputation: 838906

You can start the code in a separate process and communicate with it using RMI. If the third party code calls System.exit and kills its process, your process can continue to run and recreate the child process if necessary.

Note that there are some caveats with this approach:

  • The two processes don't share the same heap space.
  • You will need to marshal all data that is passed between the two processes. This means that the data must be serializable.
  • There will be a considerable overhead for every method call. This may give performance problems if you need to make many calls per second.

Upvotes: 2

Attila
Attila

Reputation: 28772

Writing a custom SecurityManager policy should help -- I've never done this myself :)

According to this post (scroll down to the bottom):

However, when anything in the VM tries to call System.exit(), the VM exits. Since this includes a brutal shotdown of mvn, the normal mvn process is interrupted. A SecurityManager can be used to prevent code from calling System.exit(), but nobody mentions the side-effects.

A colleague of mine mentioned that you can setup your policies system-wide, per-user and as a system-property when starting the VM and after a quick test this has proven to solve my problem. I've since managed to figure out how to set my own policy from my code (before setting up the SecurityManager) and this solves my problems.

I used the following code:

//Setup security to prevent System.exit()
SecurityManager sm = System.getSecurityManager();
URL policy = getClass().getClassLoader().getResource("jsdoc.policy");
System.setProperty("java.security.policy", policy.toString());
System.setSecurityManager(new JSDocSecurityManager(getLog()));

With a simple, wide-open, policy file reading this:

grant {
  permission java.security.AllPermission;
};

If it works it supposed to capture the System.exit() request and throw a SecurityException instead

Upvotes: 1

Related Questions