I have a standalone application in which I have to prompt the user with an confirm dialog box to save the changes made by him when he tries to shutdown the system by start-->shutdown.
I came to know that by using signalhandlers we can do it.
Can some one help me how to use signal handlers
Update May 2012 (2 and half years later)
Trejkaz comments:
On current versions of Java this signal handling code fails because the "INT" signal is "reserved by the VM or the OS".
Additionally, none of the other valid signal names actually fire when something requests the application to close (I just painstakingly tested all of the ones I could find out about...)
The shutdown hook mostly works but we find that in our case it isn't firing, so the next step is obviously to resort to registering a handler behind the JVM's back
The chapter "Integrating Signal and Exception Handling" of the "Troubleshooting Guide for HotSpot VM" mentions the signals "SIGTERM, SIGINT, SIGHUP" only for Solaris OS and Linux.
Only Exception Handling on Windows are mentioned.
Original answer (Sept 2009)
a ShutdownHook should be able to handle that case
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
public void run() {
// what you want to do
}
}));
(with caveats)
See also:
Java signal handling and termination (link is dead, see archive or mirror)
java exit signal handling:
as an illustration of simple signal handling:
public class Aaarggh {
public static void main(String[] args) throws Exception {
Signal.handle(new Signal("INT"), new SignalHandler () {
public void handle(Signal sig) {
System.out.println(
"Aaarggh, a user is trying to interrupt me!!");
System.out.println(
"(throw garlic at user, say `shoo, go away')");
}
});
for(int i=0; i<100; i++) {
Thread.sleep(1000);
System.out.print('.');
}
}
}
Related
I have a Console-Java game. The score from the game will be saved in a JSON file if Ctrl+C is pressed. The process to save the score in a JSON file works. But I don't know, how to detect Ctrl+C from the console and if this happens, I will save the score (just a method call).
With KeyListener it doesn't work on the console (only with JFrame as far as I know).
I couldn't find a solution to my problem on the internet.
Do I have to do it with Runtime? I have tried it, but it didn't work...
Runtime.getRuntime().addShutdownHook(new Thread()
{
public void run()
{
Test.mainThread.interrupt();
}
});
There are similar questions on Stackoverflow, but not for use on the console Catching Ctrl+C in Java
Adding a shutdown hook is the right way to do it, but Test.mainThread.interrupt(); probably will not work. The JVM is already shutting down. Your mainThread is unlikely to have time to respond to an interrupt; once all shutdown hooks finish, Java terminates.
Just have your shutdown hook explicitly perform whatever actions you need taken:
Runtime.getRuntime().addShutdownHook(new Thread()
{
#Override
public void run()
{
try
{
Test.saveScore();
}
catch (IOException e)
{
System.err.println("Couldn't save score before terminating.");
e.printStackTrace();
}
}
});
We know that CTRL-C closes the application and shuts down the JVM. And since it is a normal shutdown, it runs the shutdown hooks. So creating a shutdown hook is a correct approach:
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
// Do something to save the score
}));
Note that we're passing a Runnable here as the shutdown task. So we can pass an object that has the required functionality:
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
gameScores.save(); // assuming we have a gameScores object in this scope
}));
Your initial attempt by interrupting the thread can be viewed as a variant of this approach. Instead of passing the business object - gameScores - we can pass the thread to interrupt it later. But it's better to operate on the business level.
I am working on an application that needs to launch a process and wait for its output. Sometimes the process crashes (very often,) but is not really an issue since I have mitigation tasks. The problem is that Windows detects the process crashed and prompts for user input, to either check for a solution online, or just close the program.
I tried to solve this by waiting for the process to complete in a Runnable submitted to an ExecutorService and using the Future returned to specify a timeout. Speed is not really a concern for the application, and the external process is supposed to run for just a couple of seconds.
This is the code I am using:
final Process process = ...
final ExecutorService service = Executors.newSingleThreadExecutor();
try {
final Future<?> future = service.submit(new Runnable() {
#Override
public void run() {
try {
process.waitFor();
} catch (InterruptedException e) { /* error handling */}
}
});
future.get(10, TimeUnit.SECONDS);
} catch (final TimeoutException e) {
// The process may have crashed
process.destroy();
} catch (final Exception e) {
// error handling
} finally {
service.shutdown();
}
The code above worked well, but the crash dialog still pops up and it doesn't go away without user interaction.
This question presents a similar problem but from a .Net perspective and
proposes to suppress the pop up through the Windows registry, which I cannot do, given that its effect is global to all process in the machine.
Is there a way to prevent the dialog from being displayed at all?
or
Is there a way to detect the application crash and handle it directly
from Java without needing user interaction?
Additional details:
I don't have the source of the external process.
The external process is a console based application (i.e. no GUI.)
Preferably I'm looking for a pure Java based solution (no JNI.)
Thank you.
As already suggested you should use SetErrorMode win32 call. It won't change for the whole system but only for your process and it's children (which is what you want apparently).
The correct call seems to be :
SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
See also the MSDN documentation :
http://msdn.microsoft.com/en-us/library/windows/desktop/ms680621%28v=vs.85%29.aspx
Regards.
This question already has answers here:
How to get shutdown hook to execute on a process launched from Eclipse
(7 answers)
Closed 5 years ago.
I have added a shutdown hook via:
Runtime.getRuntime().addShutdownHook(myShutdownHook);
It works fine normally, but not when I click the red stop button in Eclipse. Is there a way to make the shutdown hook be called in Eclipse?
The red stop button forcibly kills the application, i.e. not gracefully, so the JVM doesn't know that the application is exiting, therefore the shutdown hooks are not invoked.
Unfortunately, there is no way (in Windows, at least) to provide a mechanism that ensures that the hook is always invoked. It's just something that may be invoked, but there is no guarantee.
I made a hack by replacing JavaProcess with decorated one:
IProcess p = launch.getProcesses()[0];
launch.addProcess(new JavaProcessDecorator(p));
launch.removeProcess(p);
And decorator is overriding terminate function.
public class JavaProcessDecorator implements IProcess {
private IProcess p;
public JavaProcessDecorator(IProcess p) {
this.p = p;
}
private boolean sigkill = false;
#SuppressWarnings("rawtypes")
#Override public Object getAdapter(Class arg) { return p.getAdapter(arg); }
...
#Override public ILaunch getLaunch() { return p.getLaunch(); }
#Override public IStreamsProxy getStreamsProxy() { return p.getStreamsProxy(); }
#Override public void setAttribute(String s1, String s2) { p.setAttribute(s1, s2); }
#Override public void terminate() throws DebugException {
if(!sigkill) {
try {
IDebugIService cs = DirmiServer.INSTANCE.getRemote("main", IDebugIService.class);
if(cs != null) cs.modelEvent(new TerminateRequest());
} catch (RemoteException e) { }
this.sigkill = true;
} else p.terminate();
}}
At first click on red button, I send a message to application asking for gently termination. If it is not working, second click on red button will kill it.
I know I'm a bit late to the party, but I found this thread seeking for help and so will probably others.
We had the same issue and solved it with an Eclipse plugin (on Linux) which provides additional stop buttons now.
I hope this serves all of you as well as it did help us :)
Red stop button just terminates the application and according to eclipse devs they can't do anything about it see this issue in eclipse bug tracker.
#Pacerier - From the Javadoc: 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. The virtual machine may also abort if a native method goes awry by, for example, corrupting internal data structures or attempting to access nonexistent memory. If the virtual machine aborts then no guarantee can be made about whether or not any shutdown hooks will be run.
If you just want to test if the hook is working or not, throw new RuntimeException() from the trigger point. This should call the shutdown hook even from Eclipse.
I was going through shutdown hook feature of java , My analysis was ..shutdownhook allows to register a thread that will be created immediatly but started only when the JVM ends ! So it is some kind of "global jvm finalizer", and you can make useful stuff in this thread (for example shutting down java ressources like an embedded hsqldb server). This works with System.exit(), or with CTRL-C / kill -15 (but not with kill -9 on unix, of course).
Please advise more practical uses and please also if possibe an small example will help to make understanding more clear..!
When a shutdown hook is added to a Runtime instance, it is added to a list of Threads to start upon clean termination of the JVM.
Example: Using shutdown hook to ensure that a java.awt.TrayIcon is removed from the system tray.
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
try {
if (SystemTray.isSupported()) {
SystemTray.getSystemTray().remove(yourTrayIcon);
}
} catch (Exception e) {
// failed to remove
e.printStackTrace();
}
}
});
More can be read in the offical documentation.
I have made a java application and have packed it into an executable jar file. Now a user can start that program from either of the following two ways:
Start if from command prompt by executing the following command on the command prompt:
java -jar "MyJar.jar"
By double clicking on that jar file.
I want that my client would adopt second approach as it is much easier than the first approach. But the problem with second approach is how to stop application before it has finished?
It is a command-line application.
And no command prompt window appears when a user double clicks on the jar file. So in this case, Will Ctrl + c work?
Stopping (exiting) the application should be inside the application. Whether it is command line or GUI based, the application developer should write code to exit it (For eg., in a command line application you might have something like Press 5 to exit, Press Esc to Exit etc) and in an application with a GUI, you will have to write code to exit when the window is closed, or an EXIT button (or others, depending on your application)
Ctrl + C is KILL the application. This is not a Normal exit. For apps with a GUI, the user would typically (in Windows) go to task manager and end the process (similar ways in other operating systems)
But these are abnormal exits - when the user wants to kill the app when, for instance, the application is no longer responding. Normal exits should be provided by the application (and therefore by the programmer - you)
I've had a similar problem. I have some Java programs that are basically long-running daemon processes. It's nice to be able to stop them and bounce (restart) them.
I've used two approaches. Both have advantages and disadvantages. One is to set up a signal handler, by putting a function like this in some class of your program (in mine, it's in the class with the main method).
import sun.misc.Signal;
import sun.misc.SignalHandler;
...
private static boolean stopNow = false;
private static boolean restartNow = false;
...
private static void handleSignals() {
try {
Signal.handle(new Signal("TERM"), new SignalHandler() {
// Signal handler method for CTRL-C and simple kill command.
public void handle(Signal signal) {
MyClass.stopNow = true;
}
});
}
catch (final IllegalArgumentException e) {
logger.warn("No SIGTERM handling in this instance.");
}
try {
Signal.handle(new Signal("INT"), new SignalHandler() {
// Signal handler method for kill -INT command
public void handle(Signal signal) {
MyClass.stopNow = true;
}
});
}
catch (final IllegalArgumentException e) {
logger.debug("No SIGINT handling in this instance.");
}
try {
Signal.handle(new Signal("HUP"), new SignalHandler() {
// Signal handler method for kill -HUP command
public void handle(Signal signal) {
MyClass.restartNow = true;
}
});
}
catch (final IllegalArgumentException e) {
logger.warn("No SIGHUP handling in this instance.");
}
}
This has worked robustly for us in production. You need a genuine Sun JRE for this to work; the one shipped with a typical Linux distro doesn't have the Signal stuff in it. It works OK on Windows too, but you don't get the HUP signal. You do need a shortcut or shellscript to launch this thing.
Also, keep in mind that signal handling is a big fat botch. Don't try to do very much inside your signal handler. You can see that my sample code simply sets static flags. Other parts of my program detect that the flag changed, and shut down. I could have experimented with more complex code inside the signal handler, but I didn't feel like taking on the QA burden.
The other approach is to structure your program as a Servlet. You'll write a class that extends HttpServlet in this case. Override Servlet.init with a method that starts your worker thread. Likewise, Override Servlet.destroy with a method that shuts yourself down.
Then you can use a Java EE container server like Tomcat to manage your starting and stopping.
If your program is a console mode program and it's doing output, Ctrl-C should be able to kill it.
If it's a GUI program, you'll want to give it a button to exit, or at least setting EXIT_ON_CLOSE as the defaultCloseOperation of your main JFrame.
ctrl+alt+suppr -> kill the javaw.exe ? :p
Or you would have to present a user interface with a stop button (see swing etc)
It depends on the User Interface. If its a Swing application then you can setDefaulCloseOperation(JFrame.EXIT_ON_CLOSE) on your main Frame. If its a console app and the user is interacting with it then you ask the user to enter a value that indicates to you that they want to stop the app. If yoy are not interacting with the user at all then ctrl-c will have to work.
Is it a GUI application or commandline.
In first case just handle the window closing event. In second case handle e.g. CTRL + C
that depends on what kind of application is it?
Is it a swing application? If so, then your app should handle when user clicks the 'close' button. There is a behavior for that. JFrame.close()
If it isnt a swing app then ctrl+c will work.
"It is a command-line application" you say.. Well you could do it so that when the user hit a button (say esc) he can write short commands to exit, restart etc..
You can do this with KeyListener. When ESC is hit (say that is the button you want the user to hit), you use Scanner on System.in, and you will do a System.exit(0); if the input is "exit".
I've used socket connection to enable kill of running instance.
//send kill signal to running instance, if any
try {
new Socket("localhost", 4000).getInputStream().read(); //block until its done
} catch (Exception e) { //if no one is listening, we're the only instance
}
//start kill listener for self
new Thread() {
#Override
public void run() {
try {
ServerSocket serverSocket = new ServerSocket(4000);
serverSocket.accept();
//do cleanup here
serverSocket.close();
} catch (Exception e) {
}
System.exit(0);
}
}.start();
You can use this one: exit()
It's possible to predefine all the action before virtual machine is totally stoppeed thus you can save your data and performa all actions to prevent the data loss.
I'm not sure it's a good way, because I've just started Java study, but it seems working.