I have particular situation in our production environment, where a particular piece of code goes into an infinite loop. The cause is mostly data specific and not able to figure out the true cause. In the mean time, what I am hoping to do is spawn a separate child thread to execute that piece of code, and if it executes for say more than 30s, want to stop that child thread from executing
Thread t = new Thread() {
public void run() {
// This is where i will the method that runs in a infinite loop
callMethodThatRunsInInfiniteLoop();
};
};
t.start();
try {
t.join(2000); // wait 2s
} catch (InterruptedException e) {
e.printStackTrace();
}
// if not completed how to break the child thread ???
unfortunately no it is a thirdparty code, and will not be able to change it so easily.
It sounds like you are trying to work around a problem in the third-party library ... or in your code calling the third-party library with bad input or something.
My advice would be to fix THAT problem, rather than trying to kill the errant thread(s). And if you can't do that, then you have two choices:
modify the 3rd party library to be interrupt aware/responsive, and then use that to stop it, or
try to find a way to "reach into" the 3rd party library's data structures (e.g. using nasty reflection) and cause it to die.
If you are resorting to the latter, then maybe you should also look at running the 3rd party library in a separate JVM so that you can forcibly kill it using the Process API.
Having said that, there are limited circumstances where Thread.stop() is actually (probably) safe to use. Basically, if the errant thread doesn't create child threads, doesn't interact with other threads and doesn't share data structures, and can't be doing class initialization when you kill it, then you are probably going to be safe. The problem is there are so many theoretical scenarios where stopping the thread could cause damage that it is hard to know that you've considered all of them.
Is there a way to cause the infinite loop code to break by throwing an exception? e.g. set some variable to
null? A possible advantage is that the affected thread (if well written) will clean up after itself and shut down more nicely than a stop().
All methods for stopping a thread 'purely externally' are deprecated and considered unsafe. The only way a thread can be safely stopped requires
modifying the code which is running to check whether it has been politely asked to stop via some stopMe variable being set; or
co-opting a variable the other thread already uses to cause the thread to quit (which is generally very bad practice); for example, by forcing it to throw an exception, as suggested by user949300.
Without this, you have no choice but to use an unsafe method, which means Thread.stop(), which is also very bad practice. This is a very bad idea, and of course the only real solution is to either change your input so that this doesn't happen, or get the third-party code fixed.
Any objects the thread was using may be in an inconsistent (and possibly unusable) state, so try to avoid letting the Thread modify anything important, and don't look at any of its output variables if you can help it.
The Thread.stop() method still seems to exist in Java SE 7, though is of course deprecated, but I can't vouch for your particular environment.
See http://docs.oracle.com/javase/1.4.2/docs/guide/misc/threadPrimitiveDeprecation.html
Depending on the implementation of the method, you could start it in its own JVM, then stop it by calling destroy() on the process:
Process process = new ProcessBuilder("java", "-cp", "/some/class/path", "com.mycompany.MyLauncher").start();
// sometime later
process.destroy();
Related
I'm wondering how to stop an unresponsive thread in Java, such that it's really dead.
First of all, I'm well aware of Thread.stop() being deprecated and why it should not be used; there are already many excellent answers on this topic, cf. [1][2]. So, the question more precisely is, whether it's actually technically possibly to kill a thread which code is not controlled by us but possibly hostile and not responding to interrupts.
In the simplest case, a hostile thread would be running while(true);, but it could as well be using up memory or other system resources to do more damage. Calling interrupt() on that thread is obviously ineffective. What about calling stop() instead?
I have run this in a debugger and, in fact, the thread really disappears. But is this approach reliable? The hostile thread could be prepared for this case; think of try{run();}catch(ThreadDeath t){run();} where it catches the ThreadDeath that is produced when we call stop() and recursively calls itself again.
As an outside observer, we cannot see what is going on; Thread.stop() always runs silently. Worst of all, the usual diagnostics won't work anymore (tried this while debugging on Corretto 1.8.0_275 Windows x64): Thread.getState() always returns RUNNABLE regardless of success in killing the thread, same goes for Thread.isAlive() (always true).
It may not be possible, at least not reliably in every scenario.
IF I understand the mechanism correctly (and there is some uncertainty there), if the code executes in such a way that there are no safepoints during the execution (for example in counted loops), it is not possible for the JVM to signal to the thread that it should stop (the thread never polls for an interrupt).
In such a scenario, you need to kill the JVM process, rather than the thread.
Some extra reading:
How to get Java stacks when JVM can't reach a safepoint
Counted loops
In a nutshell, there's no 100% reliable way to stop a Thread the way you'd like it.
Why?
This is an explanation for others who don't know why, anyone who knows the issue can skip this.
The way how threads are intended to be terminated forcefully is with the interruption state of the Thread. A Thread should be terminated with its interrupt() method is called which sets a boolean flag to true.
When the interruption flag is set to true, the Thread should terminate itself with virtually no delay.
Anyway the Thread can choose to simply ignore this and keep on running.
This is when the stop() method can be called that forces the Thread to terminate. The problem is that this method messes up concurrency, can damage objects and the program can be corrupted without a warning for the user. See Why the stop() method is deprecated?
At the end I could think of two possible ways, one is basically your way, the other one is safer but more complicated.
As an example, a hostile third party .jar which contains a Thread that refuses to terminate can cause these problems.
Quick & Dirty
This solution isn't completely safe but based on the usage this may be acceptable unless you really like security.
Try to first to call the interrupt() method on the Thread and give it a bit time to terminate.
If the Thread doesn't respond, you can either:
terminate the program and warn the user to not run that Thread again.
stop() the thread and hope for the best.
Complicated & Safe
The safest solution I can think of is creating a whole new process to run the Thread in. If the Thread doesn't want to terminate after interrupt(), you can just end the process with System.exit(-1) and let the OS handle it.
You need Inter Process Communication to communicate with the other process and that makes it a lot more complicated but also safer.
Related
How do you kill a Thread in Java?
What is an InterruptedException in Java? (Disclaimer: I've answered it)
What does java.lang.Thread.interrupt() do?
For me isAlive returns false if the process finishes due to Thread.stop.
I've made the following example, and it successfully kills the errant thread.
import java.util.Arrays;
public class BrokenThreads{
static boolean[] v = { true };
public static void call(){
try{
while(true){
Thread.sleep(200);
}
} catch ( Throwable td){
System.out.println("restarting");
call();
}
}
public static void main(String[] args) throws Exception{
Thread a = new Thread( BrokenThreads::call);
a.start();
Thread.sleep(500);
System.out.println( Arrays.toString( a.getStackTrace() ) );
while(v[0]){
a.stop();
System.out.println(a.getStackTrace().length);
v[0] = a.isAlive();
}
System.out.println("finished normally");
System.out.println( Arrays.toString( a.getStackTrace() ) );
}
}
Note that "getStackTrace" takes time, and you can see the stacktrace accumulate as recursive calls are made, until two stops happen quick enough to end the thread.
This uses two techniques to see if the thread has stopped. isAlive and the depth of the stack trace.
I think the question describes a scenario that is the reason why Thread.stop() is deprecated since ages now, but was not yet removed … just to have a 'last resort option', to be used only when being really desperate and being aware of all the negative impact.
But that call to Thread.stop() must be build into the code somehow, same as any alternative one may think about – so why not just fix the code for the thread? Or, if that is not possible because that code comes with a third party library without source code, why not replacing that library instead?
Ok, during testing, your own code may go wild, and you need an emergency break – for that, Thread.stop() is still good enough if you do not want to kill the whole JVM (what would be the better option in most of the cases). But again, you have to build this into the code before you start the test …
But in production, there should never be a thread that does not stop when receiving an interrupt. So there should be no need for a replacement of Thread.stop().
This can potentially open a can of worms like memory access violations which will kill the JVM itelf.
What you could do is isolate the thread, running .finalize() on it, then forcing the JVM to run GC operations such as Runtime.gc(), System.runFinalization() while forcing interruptions on that particular thread in order to bypass it's resurrection behavior.
I think .finalize() is effectively deprecated since java11 or maybe sooner, so it probably won't help you much.
If you really want to secure your runtime during it's operational cycles, your best bet would be to find a way to essentially map out your configuration before you start it, and have monitoring tools set up which cross-check against that map and monitor the integrity of your runtime while looking for injected classes and/or threads. ... this is assuming of course, you're attempting to guard against "virus-like" attacks in your jvm ... which is not exactly unheard of but still pretty rare.
If you're running some code off the internet, you could simply solve the issue with a call hierarchy inspection and figure out what spawns that problematic thread.
Note: If that invasive thread is calling native dll code which is looping back into it's caller, then your JVM will crash if you mark sections of it's address space as garbage collected.
I am facing an issue that when I run second instance of my application on the same port - I am getting SocketException: java.net.BindException: Address already in use: bind
The problem is that after getting this exception my application continue running.
After some hours I have noticed that (using "Get thread dump" tool) there are some threads still alive even after main is died.
I don't have access to that threads that means that I am not able to design it in way that I can interrupt them properly
Also, thread.interrupt, thread.setDaemon(true), thread.stop - nothing helped me.
How to stop that threads?
I am working on very big legacy application and threads that I want to stop are created in library that I don't access
You cannot forcibly stop threads in java. The thread has to work with you: It needs to have a core loop that looks a bit like this:
while (running && !Thread.interrupted()) {
// do something that won't take long.
try {
Thread.sleep(1000L); // or some other 'wait a while' code.
} catch (InterruptedException e) {
return;
}
}
If the code of the thread doesn't have this, and you can't change it, there's not a lot you can do about it. Thread.stop does not work on modern javas because that 'model' (throw a particular exception inside the thread, where-ever it is right now) is just something that makes for buggy software (because locks and such are unlikely to be properly closed and such): Therefore it has been deprecated for a decade now and no longer works at all. Even if it did, a thread can prevent you from stopping it.
Which leads us to the one surefire way to definitely, absolutely, kill a thread:
System.exit(0);
that'll do it. It is a common misconception that 'nice' code style is to never forcibly exit like that, with the right style being to tell all (non-daemon-status) alive threads to clean up their business and exit.
This is mistaken. Just exit. Your code should be written not to need to do any cleanup of resources, because if you write it like that, it means if someone trips over a powercable or java is hard-killed, your app just created a mess. The few cleanup jobs you do have should be registered as shutdown hooks.
So, if you want to quit the VM, just System.exit.
Of course the very first thing to do is to try and fix the other side of the code. If you can't do that and at the same time you can get a hold of those threads - you could call interrupt on them; and again, hope that the person that wrote that code knew how to handle those interrupts.
Otherwise, you are completely out of luck, unless System::exit is an option and a restart I guess. But again, this is not really your problem that some other resources, out of your control, do not clean up after themselves.
Even if they do respond to interrupts, what if you leave your database/file manager/whatever in a corrupt state?
We run an AI programming competition in which contestants will code an AI that runs on the JVM using our API we provide them. We put them into a sandbox by limiting what they can do with a SecurityManager, and during runtime they simply set several flags which are their decisions. The only interaction between our system and their AI is through these flags, so there are no bad effects on us if their thread were to suddenly die.
When an AI computes far too long, we would like to shut down their thread. However, we can't find a way of guaranteeing that we will destroy their thread. One possible reason for this is that the AI goes into an infinite loop with no blocking, making Thread.interrupt() useless. Thread.stop() is unreliable since if they are in a try catch block the ThreadDeath exception will be caught, and has no issues for us because they don't touch anything bad and we don't care if they die.
Currently we just ignore their thread and continue on without them after they time out, but their infinite loop will continue processing in the background until the JVM dies. This is unacceptable to us because we will be running matches in the background on a web server 24/7, so we want as much stability as possible. One thought has been to run each game in a separate JVM, but that is far more complex than we would like to get.
Is there any sure fire way to destroy the thread?
Provide them with a method they MUST call on a regular basis, even during their computation. If you judge they are 'dead' make the method sleep forever. Obviously his will not work if they are truly dead but you should catch most issues.
http://docs.oracle.com/javase/6/docs/api/java/lang/Thread.html#stop%28java.lang.Throwable%29
Pass in a custom subclass of Throwable that they can't know about, and you can check their code with the regex: /catch\s*(\s*Throwable/ to ensure that they don't catch Throwable anywhere.
In general, no, you should not stop an arbitrary thread in a JVM (thus the methods are deprecated). The root of the problem is that you have no idea where in the system the thread is when you kill it. In the worst case it could be in the middle of a synchronized block inside the the JVM's infrastructure that is unprepared for an unexpected exception to be thrown. (Its nearly impossible to write robust synchronized code that can be killed by an exception at arbitrary points.)
See the highly-rated answer on this question for more details:
Are java app servers able to destroy threads? If yes, how?
You might be able to get away with a cooperative design where you ask the AI thread to exit. If it does, then you're good. If it does not, then you need to restart the JVM.
After trying several things, we came to the conclusion that there is no guaranteed solution. By calling stop() on a thread, that thread is capable of catching the ThreadDeath throwable and ignoring it entirely. Thus, if it's in a while loop continuously catching it, or if it calls a method recursively that catches it, it is not guaranteed that you can kill it.
Since we didn't have any control over the code that would be running in that case, and that code was not necessarily in Java (we were also supporting Jython), the best solution we could come up with was spawning a thread that went into a loop that continuously called suspend() and then stop() on the thread. The result worked for most cases, but occasionally was unable to kill a malicious thread.
I have a program where I compile java code a user types into a text field, and then run it. A run the code in a seperate thread, so that the GUI they use to input the source code doesn't get locked up.
The GUI has an abort button that should stop the thread. My issue is that I need to stop the compiling thread no matter what is going on inside of it, which means I must account for a case where the thread is caught in an infinite loop (due to user error), and it cannot properly end itself using a safe flag. I've read up on many solutions that involve using a flag of some kind, but they aren't available to me because of this looping issue. I need to have the thread stop and the memory it's using freed (I can't just let it sit in the background forever, unless that is the only solution left). Any advice or alternative solutions? Hopefully some fresh perspectives could help squash this issue.
Edit:
Here's a sample bit of user submitted code:
public class RunMe extends SomethingThatRuns {
public void run() {
int i = 0;
while (i = 0) {
//Prepare to get stuck!
}
}
}
I'll compile this class, and then run it. This is where it will get stuck, and the run() method can never finish, or even loop to check a flag.
You can run it in a new JVM so you can kill it when you want.
Thinking about security this may be a good thing to do too.
Call stop() on the thread.
Yes, this is a deprecated method. However, it really shouldn't be "deprecated", it should be "dangerous." In some circumstances, however, there's really no choice but to use it, and the invocation of an "agent" provided by a user is one of those cases.
Make sure that your program doesn't use any data that are manipulated by this user thread; or, if you do, devise some transactional mechanism to exchange data safely between the threads.
Even this method isn't guaranteed to terminate the thread. For example, the user can catch the resulting Throwable and ignore it. Or, the thread implementation might not respond to stop() calls if the thread is in some native code. But it's your best chance.
The core issue here is the fact that the code even allows an infinite loop to be entered as part of user error. Fix that, and everything else will become easier to deal with.
Properly-behaving threads should usually terminate themselves gracefully when there's no work to do (or return quietly to a thread pool to ask for more work, if that's your application's design). If you feel like you need to have one thread forcefully kill another then you've likely got a fundamental design issue. It's fine to have one thread tell another, "Hey, you should terminate now so that I can join with you..." because that allows your threads to clean things up as they finish. Forcefully destroying threads just isn't the right way to manage these situations.
You can use them to insert a interrputed check in every loop and maybe in other places too.
I can see two options:
As you compile the user code you can edit it before. You may use
ANTLR to parse and modify the code.
There are bytecode manipulation frameworks like ASM that allow you to manipulate code that is already
compiled.
I don't think it is easy but it might be a way.
interupt(); the Thread in the gui
and in the code that the thread runs regularly check for Thread.interrupted() and throw an exception when you do especially inside loops
At a high level, you are asking how one thread might go about stopping another thread. To that end, see this SO question Stopping a Thread in Java?.
I have a GUI which resembles an interpreter. It allows the user to write a script in Jython (implementation of Python in Java) and run it whenever he wants. Apart from that, I also wish to allow the user to instantly terminate the run whenever he wants.
Thing is, I don't really know how to do it. The script is being run on a different Thread, but I don't know of any secure way to stop/interrupt/terminate a thread in the middle of its run, let alone not knowing what is being run by the thread/script (it could be a simple task or maybe some sort of a heavy SQL query against a DB, and a DB is something which requires careful resource handling).
How can I instantly terminate such run on demand?
Unfortunately there is no safe way to terminate a thread instantly and safely. That is part of the reason why Thread.stop has been deprecated.
It is a complicated problem, and it really depends on how your thread works. A generic solution for all threads to do this does not exist. It sounds like your thread is not in a loop, so polling a variable on a loop will not do. But you may be able to a variation:
MyThread extends Thread {
PythonProcess p;
void run() {
p = startPython();
}
void stopMe() {
p.halt();
}
}
As a last resort you can still use the deprecated Thread.stop, but it will be unsafe and should be avoided if at all possible. Other then that maybe you can do a process fork and handle it manually at the OS level, but that is not very java like.