This may sound like it's been asked before, but it's a bit different than the norm. I don't want the typical (After the user has run the program, I want it to ask "would you like to go again?"). I want to start a process (by typing a certain string which I've accomplished) and have it run for an infinite amount of time until the user stops it. There's no way of knowing how long it will run. This program happens to be a timer. So I need it to calculate how long it's been running, be able to be stopped at any given moment by the user, and print out how long it ran.
As of now, I'm not using any UI/GUI. Keeping it as simple as possible.
Set up a shutdown hook (code that runs when the JVM is halting):
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
#Override
public void run() {
// print stuff here
}
}));
Get the user to type ctrlc at the command line to halt execution - your hook will run to print what you like as the JVM comes down.
Edit:
The above is brutal but simple, however if you didn't want to terminate the whole JVM, you're getting into the realm of "server events" to drive behaviour, which can take many forms to cause an action:
running your worker task in a separate thread and waiting for a command(s) at the terminal to halt (or other action) that thread - this is what I'd try first, and it would be very educational for you to do this
monitor a file system looking for the presence/absence of a file (lame, but it works with minimal code)
listening to ports for messages, an HTTP port of a web server is usually the weapon of choice, but we're starting to get a bit heavier on the server side
monitoring a JMS queue for messages - we're in Java EE space now with still more heaviness
any other "change in state" you care to implement
Edit 2:
This is a minimal implementation that works using a shutdown hook (start on the command line and press ctrlc to end and run the calculation code):
public static void main(String[] args) throws Exception {
final long start = System.currentTimeMillis();
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
#Override
public void run() {
double hours = (System.currentTimeMillis() - start) / 3600000d;
System.out.println("Please enter the hourly rate");
double hourlyRate = new Scanner(System.in).nextDouble();
System.out.format("Program ran for %01.3f hours and cost $%02.2f", hours, hourlyRate * hours);
}
}));
Thread.sleep(Long.MAX_VALUE); // Sleep "forever"
}
Could you start a Thread with daemon true, and then read a line in System.input, then interrupt the thread. java.util.Timer is possible too.
Related
I have a program that creates a lot of information and I take that information and throw it into a thread by way of
final static ExecutorService service = Executors.newFixedThreadPool(10);
and pass it information via:
service.submit(new threadTry(str));
Where threadTry is the thread that takes the information, passes it inside command line arguments to generate a command, executes the command, then the cmd process runs the next process if criteria met.
Then the Executor service takes the list of submitted jobs, runs the 10 threads I've limited it to with the information given to them, creates a process which runs a command line window which can pop up another if a certain criteria is met. The command line window and the additional window that pops up do in fact terminate and the thread containing the command line window does terminate as well. The ExecutorService starts another thread with another bit of information. However, The cmd.exe and the other program are listed in windows 7 resource monitor as terminated. My program generates between 150-250 of these terminated cmd's/second (The handles to the javaw.exe process goes up and up with this). Only after I forcibly stop the main program, all the terminated processes are released.
My main problem is that I have to pass so much information that my program gets to about 56% done, then halts. I assume this is because the operating system cannot keep track of so many processes (even though they are terminated, but still listed). Halting is not caused by main program, it generates all information and terminates within 2 seconds (without doing anything with the info). With the processing of the information, my program takes about 2-3 hours to get to 56%.
public class threadTry extends Thread {
String str="";
public threadTry(String str){
this.str=str;
}
public void run(){
try{
String[] cmd={"...",str,"..."}; //input many arguments into cmd
ProcessBuilder probuilder= new ProcessBuilder( cmd );
Process process = probuilder.start();
if(!process.waitFor(5, TimeUnit.SECONDS)){//if we wait longer than 5 seconds,
//then print this message (this is the standard wait for the process that
//waits until termination)
System.out.println(str+": has exited with thread: "+this.getId());
}
int exitValue = process.exitValue();
if(exitValue!=3){
System.out.println("---------------------------------------------------");
System.out.println("\n\nExit Value is " + exitValue+" For: "+str);
System.out.println("---------------------------------------------------");
}
process.destroyForcibly();//does nothing to help clear the already
//terminated process
}catch(Exception e){
e.printStackTrace();
}
}
}
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.
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.
I am trying to make a Java program which will run several other unrelated Java programs, specifically a Minecraft server.
Currently, I am trying to work out how to end a java.lang.Process gracefully.
This is the code for my spawner program:
http://dl.dropbox.com/u/26746878/SpawnerSource/Main.java.txt
And this is the code for the program which is spawned:
http://dl.dropbox.com/u/26746878/SpawnerSource/Tester.java.txt
What I do is run my spawner program. Then, after a few seconds, I terminate it with Ctrl-C.
What I want to see is my program output 'Shutting Down' followed by 'Ending'. I also want to see a file 'test.txt'.
What I actually see is only 'Shutting Down', with no 'Ending' nor 'test.txt'
I believe the problem is that Process.destroy() is forcefully ending the process without letting the shutdown hooks run.
Is there an alternative to Process.destroy() which will exit the process gracefully (ie: as if I had pressed Ctrl-C)?
You should never destroy a working process as it might get the whole OS into an unstable state (believe me, this caused us 2 hours downtime and cost 10000$ to my company :( )
What you should do instead is as #Kane mentioned, send a shutdown request to all your child processes and wait until they are all finished (every child process sends an RMI notification back to the main process right before gracefully exiting)
class ParentProcess{
Map<int, CountDownLatch> finishSignals = new ConcurrentHashMap<int, CountDownLatch>();
public void startProcess(){
// Start child process
// get its ID
// and create a count down latch for it
finishSignals.add(processId, new CountDownLatch(1));
}
public void shutDownProcess(processId){
// Send an RMI request to process ID to shutdown
}
// RMI request sent from child process before stopping
public void processFinishedNotification(processId){
finishSignals[processId].countDown()
}
public void waitForChildsToFinish(){
// This for loop will block until all child processes have sent a finish notification
for(CountDownLatch childFinishSignal : finishSignals){
childFinishSignal.await();
}
}
}
You may want to look into Remote Method Invocation, and have your spawner process ask the child processes to shut themselves down instead of having the spawner process kill the child processes itself.
I have a servlet filter that carries some logic and produces output before a request is served by it's primary page. I have a new need to send out the output a few seconds later than at the moment it is generated (with ~10s delay). Because of certain poor design choices made earlier I can't move the position of the filter just to have the output sent after.
I've chosen to spawn off a thread and delay transmission of the message in there. I'm currently not taking any explicit steps to halt execution of this thread. I'm not sure if everything is getting cleaned up properly though. Should I be using join() or interrupt() or any other Thread methods to clean up safely after this?
So within the main servlet code I have something like this...
Thread t = new Thread(new MessageSender(message, 10000));
t.start();
//Carry on.. la la la
While there are other fields in this class, I just stripped out a lot of the non-essential stuff like making DB connections etc to make the point clear.
private static class MessageSender implements Runnable {
String message;
int delay;
public MessageSender(String message, int delay) {
this.message = message;
this.delay = delay;
}
public void run() {
try {
Thread.sleep(delay);
System.out.println(new java.util.Date() + ": hello world");
} catch (InterruptedException e) {
// Do blah
} catch (Exception e) {
// Do blah blah
} finally {
// Close connections and stuff
}
}
}
Your code should be fine, the VM will clean up the thread once it completes.
However, I'd advise not using raw threads like that, but instead using a java.util.concurrent.ScheduledExecutorService, creating using java.util.concurrent.Executors. It's a nicer abstraction that would better control your thread allocation.
Yes, everything will be properly cleaned up. Thread dies after finishing run() method and as you have no more references to that thread object - it will be properly garbage-collected.
Just be sure that "Thread t" object will not be referenced by anything. To be sure on that, you can use:
(new Thread(...)).start();
The servlet specification explicitly states (section "Thread safety") that request and response objects are not guaranteed to be thread-safe, and that if those objects are handed off to other threads, then the application is responsible for ensuring that these objects are synchronized and that they are accessed only within the scope of the servlet's service method. In other words, you must .join() those threads.
I've just had to answer the same question myself :)
I can acknowledge that the threads are indeed cleaned up after they complete. If you're not completely certain the spawned threads ever die, you should be able to monitor the process and see how many threads it's currently running at. If the number keeps growing, something's outta control.
On a Unix-system, you can use the ps command, but I'm rusty, so I asked google instead of reading the man-page.
One of the first hits on google was This script that lists threads for each process. Output looks like this
PID TID CLS RTPRIO STAT COMMAND WCHAN
....
16035 16047 TS - S (java)
16035 16050 TS - S (java)
16035 16054 TS - S (java)
16035 16057 TS - S (java)
16035 16058 TS - S (java)
16035 16059 TS - S (java)
16035 16060 TS - S (java)
....
And I just grep the output for the process id (pid) of the process I want to watch and count the number of lines, each one corresponding to a thread. Like this:
morten#squeeze: ~$ sh /tmp/list_threads.sh | grep 16035 | wc -l
20
So the program I'm currently watching (PID 16035) has 20 threads running.
This required no knowledge of jconsole or any changes to the code. The last part is probably the most important part, as I haven't written the program myself, so now I don't have to read and understand the program.