This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Java: How could I “intercept” Ctrl+C in a CLI application?
On Windows I start a java non gui application doing a task
Then press CNTL-C and the program just exits, none of my interrupt handling code seems to trigger, even putting a try/catch in the main method never displays a stack trace to indicate it has been interuppted.
public static void main(final String[] args) throws Exception
{
try
{
CmdLineDecoder cld = new CmdLineDecoder();
cld.start(args);
System.exit(0);
}
catch(Exception e)
{
e.printStackTrace();
throw e;
}
}
I'm clearly misunderstanding the effect of Cntl-C, but what ?
You can't do general signal handling in java, but you can handle Ctrl-c.
If you need to do something upon VM shutdown, use a shutdown hook: Runtime.addShutdownHook.
From the docs:
The Java virtual machine shuts down in response to two kinds of events:
The program exits normally, when the last non-daemon thread exits or when the exit (equivalently, System.exit) method is invoked, or
The virtual machine is terminated in response to a user interrupt, such as typing ^C, or a system-wide event, such as user logoff or system shutdown.
I've used this in the past on Windows/OSX.
Related
This question already has answers here:
Exiting an application gracefully?
(3 answers)
Closed 3 years ago.
I am developing a java standalone application where it has to upload batch of files to rest api. I want to stop the application whenever I needed from the command prompt but if the application is in the process of uploading a file it has to complete that and has to stop before starting to upload another file.
It cannot stop any time you wish because (I assume) your program runs on a single thread, and thus, must complete every task in the order it is given.
When uploading a list of files, you can provide some kind of listener in the front on one thread while the files upload in the background. When Thread1 recieves the information that it needs to quit, it could then set some kind of global boolean that thread 2 checks before it starts uploading the second file.
Making the upload process a background thread allows you to modify the program in the process.
If you were looking for documentation on gracefully exiting the program in general, it can be found here: http://docs.oracle.com/javase/7/docs/api/java/lang/Runtime.html#exit%28int%29
You could do a quick check on an isUploading flag in your application's exit code JVM shutdown hook. If false, continue with the exit. If true, wait for the upload process to complete or timeout.
See https://stackoverflow.com/a/17792988/2884613.
public class Main {
public static void main(String[] args) {
Runtime r = Runtime.getRuntime();
r.addShutdownHook(new ShutdownHook());
while(Flag.flag){
System.out.println("Application is still running......");
}
if(!Flag.flag) {
System.out.println("goin to exit the application");
Flag.shutdownFlag = false;
return;
}
}
}
public class Flag {
public static boolean flag = true;
public static boolean shutdownFlag = true;
}
public class ShutdownHook extends Thread {
public void run() {
System.out.println("Shutdown hook is initiated");
Flag.flag = false;
while (Flag.shutdownFlag) {
System.out.println("Waiting for application to complete the task..");
}
}
}
I am running the jar in command prompt. As soon as we want to stop the application we can just give ctrl+c in command prompt.
I started a java program from c# by using
...
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.WorkingDirectory = "C:\\path\\to\\jar\\";
startInfo.FileName = "C:\\Windows\\Sysnative\\java.exe";
startInfo.Arguments = "-jar JavaProg.jar";
process = new Process();
process.StartInfo = startInfo;
try {
process.Start();
}
...
The process is then running continuously until I want it to stop. The java program has a shutdown hook that should be able to catch normal kill signals. E.g., if I run the jar from a bat script, then pressing Ctrl+c in the cmd window will trigger the shutdown hook, but closing the cmd window will terminate the process without triggering the shutdown hook (similar to End Process in the task manager).
So in order to stop the java program from C# I tried:
process.CloseMainWindow();
or
process.Kill();
The CloseMainWindow method has no effect on the java process, and Kill terminates it without triggering the shutdown hook. So what can I do in order to close the java program gracefully from within the C# code?? [Do I need to make modifications in my Java program to intercept the CloseMainWindow signal? Is there a way to mimic the behavior of Ctrl+c on the cmd window from C#? Must I create some path of communication between my C# and Java codes like a pipe or socket?]
P.S. The C# code is simply a wrapper for the java code in order to run it as a service on windows (I can't use existing tools such as RunAsService for that purpose).
General description of the program:
My java program doesn't create any windows. It has a few threads, the main one runs in a loop just waiting for connections, another performs a specific task on an incoming connection, another thread does periodic updates from a web server, and there's the shutdown hook. Usually, the program is run from the command prompt (or terminal on linux), and takes user input only when it is loading for the first time, after which it can be run again without more user input. The program outputs logs to a file. My shutdown hook:
...
shutdownHook = new ShutdownHook();
Runtime.getRuntime().addShutdownHook(shutdownHook);
...
class ShutdownHook extends Thread {
public void run() {
// log the shutdown is started
// terminate classes
// interrupt and join the other threads
// log the shutdown is done
}
}
The best way of doing this is for your C# program to get a handle to the Java program's stdin. That way, the C# program can send a message to the Java program whenever it likes, and the Java program can listen out for a message asking it to die.
This has the advantage that you don't need to worry about shutdown hooks: the program can do whatever processing it needs to when it receives a shutdown message. It is also a lot more flexible: if, later on, you want the C# program to send other control messages, that can be easily added.
On the Java side, you'd need a separate thread that opens System.in and reads from it, and performs whatever shutdown you need when it gets the right message in.
On the C# side, it looks as though you want
startInfo.RedirectStandardInput = true;
startInfo.UseShellExecute = false;
and then when you want to send a message:
process.StandardInput.WriteLine(...some message...);
(but I am a Java coder, so I am uncertain as to whether I've got the C# right here).
This attempts to close all notepad windows. Note that you can end up getting prompted if you want to save.
[DllImport( "user32.dll", CharSet = CharSet.Auto, SetLastError = false )]
static extern IntPtr SendMessage( IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam );
static uint WM_CLOSE = 0x10;
public void CloseWindow( IntPtr hWindow )
{
SendMessage( hWindow, WM_CLOSE, IntPtr.Zero, IntPtr.Zero );
}
public void test_close()
{
foreach ( System.Diagnostics.Process p in System.Diagnostics.Process.GetProcessesByName( "notepad" ) )
{
CloseWindow(p.MainWindowHandle);
}
}
You need to use GenerateConsoleCtrlEvent:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms683155(v=vs.85).aspx
You can call this using P/Invoke.
This will allow you to generate a Ctrl+C event which your Java program will handle in the same way as it does if you press Ctrl+C in the command window.
Note: However this will only work if the process has a console. Java initialises the Ctrl+C handler on startup so you need to make sure the program has a console when it starts. You can do this by calling AllocConsole in the calling program to create a console, and the java program will inherit the console.
http://msdn.microsoft.com/en-us/library/windows/desktop/ms681944(v=vs.85).aspx
Ive got the following ShutdownHook to detect when the application is exited:
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
public void run() {
// Do what you want when the application is stopping
sendMsg("", "goOfflineExit", "12");
}
}));
This works perfectly on Mac os but for some reason nothing gets fired on Windows.
Any ideas what im missing?
I can think of two possible explanations:
The sendMsg(...) call may be happening too late; e.g. after streams have been closed or flushed.
The sendMsg(...) call may be throwing an exception. Uncaught exceptions thrown in a shutdown hook typically don't get reported.
If you showed us the code of sendMsg we might be able to figure out a more definite answer.
When I use 4 threads for my program there is usually no problems, but today I increased it to 8 and I noticed 1-3 threads stop working without throwing any exceptions. Is there anyway to find out why they are stopping? is there anyway to make the thread restart?
This is how the structure of my thread is
public void run()
{
Main.logger.info(threadName + ": New Thread started (inside run)");
while (true)
{
try
{
//all my code
//all my code
//all my code
}
catch(Exception e)
{
Main.logger.error("Exception: " + e);
try
{
Thread.sleep(10000);
}
catch (InterruptedException e1)
{
e1.printStackTrace();
}
}
finally
{
try
{
webClient.closeAllWindows();
Thread.sleep(3000);
Main.logger.info(threadName + ": Closed browser!");
}
catch (Exception e)
{
Main.logger.error("Exception: " + e);
}
}
}// end while
}
Regards!
Note that an Error is not an Exception; it's a Throwable.
So, if you catch Exception, Errors will still get through:
private void m() {
try {
m(); // recursively calling m() will throw a StackOverflowError
} catch (Exception e) {
// this block won't get executed,
// because StackOverflowError is not an Exception!
}
}
to catch "everything", change your code to this:
try {
...
} catch (Throwable e) {
// this block will execute when anything "bad" happens
}
Note that there might be little you can do if an Error occurs. Excerpt from javadoc for Error:
An Error is a subclass of Throwable that indicates serious problems that a reasonable application should not try to catch. Most such errors are abnormal conditions. The ThreadDeath error, though a "normal" condition, is also a subclass of Error because most applications should not try to catch it.
Is there anyway to find out why they are stopping?
That's a bit tricky.
A Java thread can terminate for two reasons:
it can return from its run() method,
it can terminate due to an exception being thrown and not caught on the thread's stack.
You can detect the latter case by using an "UncaughtExceptionHandler" for the thread, but the former case can't be positively detected unless you modify your thread's run() method to log the event ... or something like that.
I guess, the other way to figure out what is going on would be to attach a debugger to the JVM and get it to report the uncaught exception to you.
(I suspect that the reason you are not seeing any exceptions is that your threads' run methods are not catching / logging all exceptions, AND they don't have an uncaught exception handler.)
is there anyway to make the thread restart?
No. There is no way to restart a Thread that has terminated.
If you are running from the command line, you can have dump states of all threads to the console. On windows you do this by hitting Ctrl+Break, under linux, by sending the QUIT signal to the process with 'kill'.
Please refer to An Introduction to Java Stack Traces
Sending a signal to the Java Virtual Machine On UNIX platforms you can
send a signal to a program by using the kill command. This is the quit
signal, which is handled by the JVM. For example, on Solaris you can
use the command kill -QUIT process_id, where process_id is the process
number of your Java program.
Alternatively you can enter the key sequence \ in the window
where the Java program was started. Sending this signal instructs a
signal handler in the JVM, to recursively print out all the
information on the threads and monitors inside the JVM.
To generate a stack trace on Windows 95, or Windows NT platforms,
enter the key sequence in the window where the Java
program is running, or click the Close button on the window.
Thread priority on one of them could be too high, try setting them the same level through?
Deadlocking is possible if there is any control on each and other between them.
How do you handle clean up when the program receives a kill signal?
For instance, there is an application I connect to that wants any third party app (my app) to send a finish command when logging out. What is the best say to send that finish command when my app has been destroyed with a kill -9?
edit 1: kill -9 cannot be captured. Thank you guys for correcting me.
edit 2: I guess this case would be when the one calls just kill which is the same as ctrl-c
It is impossible for any program, in any language, to handle a SIGKILL. This is so it is always possible to terminate a program, even if the program is buggy or malicious. But SIGKILL is not the only means for terminating a program. The other is to use a SIGTERM. Programs can handle that signal. The program should handle the signal by doing a controlled, but rapid, shutdown. When a computer shuts down, the final stage of the shutdown process sends every remaining process a SIGTERM, gives those processes a few seconds grace, then sends them a SIGKILL.
The way to handle this for anything other than kill -9 would be to register a shutdown hook. If you can use (SIGTERM) kill -15 the shutdown hook will work. (SIGINT) kill -2 DOES cause the program to gracefully exit and run the shutdown hooks.
Registers a new virtual-machine shutdown hook.
The Java virtual machine shuts down in response to two kinds of events:
The program exits normally, when the last non-daemon thread exits or when the exit (equivalently, System.exit) method is invoked, or
The virtual machine is terminated in response to a user interrupt, such as typing ^C, or a system-wide event, such as user logoff or system shutdown.
I tried the following test program on OSX 10.6.3 and on kill -9 it did NOT run the shutdown hook, as expected. On a kill -15 it DOES run the shutdown hook every time.
public class TestShutdownHook
{
public static void main(String[] args) throws InterruptedException
{
Runtime.getRuntime().addShutdownHook(new Thread()
{
#Override
public void run()
{
System.out.println("Shutdown hook ran!");
}
});
while (true)
{
Thread.sleep(1000);
}
}
}
There isn't any way to really gracefully handle a kill -9 in any program.
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 only real option to handle a kill -9 is to have another watcher program watch for your main program to go away or use a wrapper script. You could do with this with a shell script that polled the ps command looking for your program in the list and act accordingly when it disappeared.
#!/usr/bin/env bash
java TestShutdownHook
wait
# notify your other app that you quit
echo "TestShutdownHook quit"
I would expect that the JVM gracefully interrupts (thread.interrupt()) all the running threads created by the application, at least for signals SIGINT (kill -2) and SIGTERM (kill -15).
This way, the signal will be forwarded to them, allowing a gracefully thread cancellation and resource finalization in the standard ways.
But this is not the case (at least in my JVM implementation: Java(TM) SE Runtime Environment (build 1.8.0_25-b17), Java HotSpot(TM) 64-Bit Server VM (build 25.25-b02, mixed mode).
As other users commented, the usage of shutdown hooks seems mandatory.
So, how do I would handle it?
Well first, I do not care about it in all programs, only in those where I want to keep track of user cancellations and unexpected ends. For example, imagine that your java program is a process managed by other. You may want to differentiate whether it has been terminated gracefully (SIGTERM from the manager process) or a shutdown has occurred (in order to relaunch automatically the job on startup).
As a basis, I always make my long-running threads periodically aware of interrupted status and throw an InterruptedException if they interrupted. This enables execution finalization in way controlled by the developer (also producing the same outcome as standard blocking operations). Then, at the top level of the thread stack, InterruptedException is captured and appropriate clean-up performed. These threads are coded to known how to respond to an interruption request. High cohesion design.
So, in these cases, I add a shutdown hook, that does what I think the JVM should do by default: interrupt all the non-daemon threads created by my application that are still running:
Runtime.getRuntime().addShutdownHook(new Thread() {
#Override
public void run() {
System.out.println("Interrupting threads");
Set<Thread> runningThreads = Thread.getAllStackTraces().keySet();
for (Thread th : runningThreads) {
if (th != Thread.currentThread()
&& !th.isDaemon()
&& th.getClass().getName().startsWith("org.brutusin")) {
System.out.println("Interrupting '" + th.getClass() + "' termination");
th.interrupt();
}
}
for (Thread th : runningThreads) {
try {
if (th != Thread.currentThread()
&& !th.isDaemon()
&& th.isInterrupted()) {
System.out.println("Waiting '" + th.getName() + "' termination");
th.join();
}
} catch (InterruptedException ex) {
System.out.println("Shutdown interrupted");
}
}
System.out.println("Shutdown finished");
}
});
Complete test application at github: https://github.com/idelvall/kill-test
There are ways to handle your own signals in certain JVMs -- see this article about the HotSpot JVM for example.
By using the Sun internal sun.misc.Signal.handle(Signal, SignalHandler) method call you are also able to register a signal handler, but probably not for signals like INT or TERM as they are used by the JVM.
To be able to handle any signal you would have to jump out of the JVM and into Operating System territory.
What I generally do to (for instance) detect abnormal termination is to launch my JVM inside a Perl script, but have the script wait for the JVM using the waitpid system call.
I am then informed whenever the JVM exits, and why it exited, and can take the necessary action.
You can use Runtime.getRuntime().addShutdownHook(...), but you cannot be guaranteed that it will be called in any case.
Reference https://aws.amazon.com/blogs/containers/graceful-shutdowns-with-ecs/
import sun.misc.Signal;
import sun.misc.SignalHandler;
public class ExampleSignalHandler {
public static void main(String... args) throws InterruptedException {
final long start = System.nanoTime();
Signal.handle(new Signal("TERM"), new SignalHandler() {
public void handle(Signal sig) {
System.out.format("\nProgram execution took %f seconds\n", (System.nanoTime() - start) / 1e9f);
System.exit(0);
}
});
int counter = 0;
while(true) {
System.out.println(counter++);
Thread.sleep(500);
}
}
}
There is one way to react to a kill -9: that is to have a separate process that monitors the process being killed and cleans up after it if necessary. This would probably involve IPC and would be quite a bit of work, and you can still override it by killing both processes at the same time. I assume it will not be worth the trouble in most cases.
Whoever kills a process with -9 should theoretically know what he/she is doing and that it may leave things in an inconsistent state.