Forcefully terminating a thread I didn't write in Java - java

Everywhere I look about how to forcefully stop a thread in Java, I see "just do an exit variable check instead, your program is broken if you need to force kill."
I have a rather unique situation though. I am writing a Java program that dynamically loads and runs other Java classes in a separate thread. (No comments about security risks please, this is a very specific use case).
The trouble is, since other people will have written the classes that need to be loaded, there's no way to guarantee they'll implement the stop checking and whatnot correctly. I need a way to immediately terminate their thread, accepting all the risks involved. Basically I want to kill -9 their thread if I need to. How can I do this in Java?
Update: here's a bit more info:
This is actually an Android app
The user code depends on classes in my application
A user class must be annotated with #UserProgram in order to be "registered" by my application
The user also has the option of building their classes right into the application (by downloading a project with the internal classes already compiled into a libraries and putting their classes in a separate module) rather than having them dynamically loaded from a JAR.
The user classes extend from my template class which has a runUserProgram() method that they override. Inside that method, they are free to do anything they want. They can check isStopRequested() to see if I want them to stop, but I have no guarantee that they'll do that.
On startup, my application loads any JARs specified and scans both all the classes in the application and the classes in those JARs to find any classes annotated with the aforementioned annotation. Once a list of those classes is built, it is fed into the frontend where the UI provides a list of programs that can be run. Once a program is selected, a "start" button must be pressed to actually start it. When it is pressed, the button changes to a "stop" button and a callback is fired into the backend to load up the selected class in a new thread and call the runUserProgram() method. When the "stop" button is pressed, a variable is set which causes isStopRequested() to return true.

You can kill -9 it by running in its own process i.e. start with a ProcessBuilder and call Process.destroyForcibly() to kill it.
ProcessBuilder pb = new ProcessBuilder("java", "-cp", "myjar.jar");
pb.redirectErrorStream();
Process process = pb.start();
// do something with the program.
Scanner sc = new Scanner(process.getOutputStream());
while (sc.hasNextLine()) {
System.out.println(sc.nextLine());
}
// when done, possibly in another thread so it doesn't get blocked by reading.
process.waitFor(1, TimeUnit.SECONDS);
if (process.isAlive())
process.destroyForcibly();
Java 8 had Thread.stop(). The problem is that it could only work reasonably for very limited use cases, so limited you were better off using interrupts, and if the code isn't trusted, neither are any good.

There is the deprecated Thread.stop() but don't use it.
There is no way to cleanly terminate another thread without it cooperating.
The thread can be in a state where it allocated some memory, or added some objects to some global state, locked some mutexes, etc. If you kill it at the wrong moment, you risk leaking memory or even causing a deadlock.

It would be possible through JNI, under Windows there is a TerminateThread API that you can call, there is (hopefully) probably a similar thing under Android. The trouble will be getting the thread's native handle, you would need to obtain that when your user "program" is first loaded, probably by calling another JNI method from the thread in question as part of the initialisation process and getting the current thread handle from that.
I have not tried this myself, best case is that this "works" and kills the thread, but it is going to cause that thread to leak resources. Worst case is that it will leave the JVM in an inconsistent state internally, which will probably crash your entire application.
I really think this is a Bad Idea.
A better design, if you want to allow this, is to run your user code in another process and communicate with it via sockets or pipes. This way you can relatively safely terminate the other process if necessary. It's more work, but it's going to be a lot better in the long run.

You shold use Thread.interrupt().

Related

How to have Process spawned by ProcessBuilder run a callback on completion/termination?

I'm writing a separate thread to monitor an OS process spawned by Java's ProcessBuilder. The process can sometimes get out of control. After a given timeout period, I want to kill the process if it's still running. I can paste my code in if it's helpful (please ask), but the only detail directly relevant to the question is that I'm using Process::waitFor to specify the timeout after which the process will be killed.
The problem is that this code design is relatively inefficient. As even the documentation for Process::waitFor says,
The default implementation of this methods polls the {#code exitValue}
to check if the process has terminated. Concrete implementations of this
class are strongly encouraged to override this method with a more
efficient implementation.
I'm thinking a much more efficient design would be to specify a callback to be executed after the process completes. I could execute my own timeout method that would kill the process if it were still running. But the callback, if run, would cancel the timeout kill method.
Can I implement a callback pattern for a process spawned by ProcessBuilder?
I'm looking at the ProcessBuilder.start(Redirect[] redirects) and wondering if I could just tack the execution of the callback at the end of this method. Problem is that the class is final, so I can't subclass it. I'd have to copy and modify. But I'd also have to duplicate such dependencies as ProcessEnvironment and ProcessImpl, which are not public, as well as being final. Ugh.
Is maybe there some way to extend the abstract class Process to use a callback? That class seems to have/be the only space left by the authors of Java for fixing up the inefficient code they've left.
Or perhaps there's another way to make Process::waitFor more efficient?

Multiprocessing in Java with Killable thread

I have a scenario in which I am running unreliable code in java (the scenario is not unlike this). I am providing the framework classes, and the intent is for the third party to overwrite a base class method called doWork(). However, if the client doWork() enters a funked state (such as an infinite loop), I need to be able to terminate the worker.
Most of the solutions (I've found this example and this example) revolve around a loop check for a volatile boolean:
while (keepRunning) {
//some code
}
or checking the interrupted status:
while (isInterrupted()) {
//some code
}
However, neither of these solutions deal with the the following in the '//some code' section:
for (int i = 0; i < 10; i++) {
i = i - 1;
}
I understand the reasons thread.stop() was depreciated, and obviously, running faulty code isn't desirable, though my situation forces me to run code I can't verify myself. But I find it hard to believe Java doesn't have some mechanism for handling threads which get into an unacceptable state. So, I have two questions:
Is it possible to launch a Thread or Runnable in Java which can be reliably killed? Or does Java require cooperative multithreading to the point where a thread can effectively hose the system?
If not, what steps can be taken to pass live objects such that the code can be run in a Process instead (such as passing active network connections) where I can actually kill it.?
If you really don't want to (or probably cannot due to requirement of passing network connections) spawn new processes, you can try to instrument code of this 'plugin' when you load it's class. I mean change it's bytecode so it will include static calls to some utility method (eg ClientMentalHealthChecker.isInterrupted()). It's actually not that hard to do. Here you can find some tools that might help: https://java-source.net/open-source/bytecode-libraries. It won't be bullet proof because there are other ways of blocking execution. Also keep in mind that clients code can catch InterruptedExceptions.

Exiting one thread closes all

I have a java app which has a menu. One of the menu items is Exit. Which is defined as follows:
item_exit.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
System.exit(0);
}
});
Another menu item is New, which makes another instance (?) of the same program run in parallel. It is defined as follows:
item_new.addActionListener(new ActionListener() {
MyApp app = new MyApp();
app.start();
}
});
It works as desired except for one problem. It's that when I close one of them, both of them close. The entire app is built on one JFrame object. I don't think changing the default close operation of it will help. I think the issue is with system.exit(0). But, what is the alternative to fix this? I only want the thread I closed to close, not all of them. Thanks.
Creating an object and callings its start() method doesn't make another program run in parallel. It only creates an object, in the same JVM, and executes its start() method, in the same JVM.
System.exit() exits the JVM, so everything running in this JVM stops running.
To make a JFrame invisible, you call setVisible(false) on it. That won't stop the JVM.
System.exit(0); makes the entire Java machine to quit, with everything that is running within. Try not to use this, unless you really need this to happen.
For quitting, perhaps try checking this How to close a Java Swing application from the code
System.exit(0) quits the complete program, not only the current thread. If you want to quit a thread, you have two options: a thread automatically quits as soon as the corresponding Runnables run() method finishes, or you can kill the thread using thread.stop() (just for completeness, shouldn't be used).
Please read the documentation for System.exit(). It specifically states:
Terminates the currently running Java Virtual Machine.
This means the JVM will terminate, and all of your threads with it.
System.exit(0) shuts the whole JVM down.
Your two instances run on the same JVM : you don't fork a process, you just create another instance of your MyApp class. So it is obvious that both "applications" will be killed.
Instead of calling System.exit(0), you should send a termination signal to the JFrame you want to close
frame.dispatchEvent(new WindowEvent(frame, WindowEvent.WINDOW_CLOSING));
This way, only that JFrame (or "application") will be killed.
Another option would be to fork a whole new process. For that, I recommend you take a look at the Process class.
Basically, you'll need to change the action of "Exit" so that it's able to detect when there's another "app" currently running ... and to do something plausible in that case. Maybe you alert the user that the other activity hasn't finished yet, and warn him that if he really wants to exit now, the other activity will be abandoned. Maybe you launch the other activity in such a way that it is altogether separate and therefore doesn't care. There are several good alternatives, so this really becomes a design decision on your part: what strategy makes the most intuitive sense for you, and for your users?

Signals in Java

I was use C++ signals
sigaction
struct sigaction sigact;
and set all attributes to use signals
now I want to use it in Java what's the equivalent in java
to the include "signal.h"
I have two threads:
one run from the beginning of the program
and the other run at the signal Alarm
I was implement the functionality in C++ using Signals as shown and now I want to implement it using java
Edited to put my Goal:
actually my Goal to run the second Thread When the signal arrives from the first thread
Thus sounds like a typical "XY-Problem".
In plain Java you have no access to OS-signal. They are platform specific and Java strifes to be platform agnostic. Also: calling Java from a signal handler with JNI might be "fun" (as explained in Dwarf Fortress).
So you have to go back to the drawing board and think about what is the problem you want to solve and stop thinking about how to solve it with signals.
That said: if you insist on signals and are not afraid to use internal stuff which might change on a whim: Take a look at sun.misc.Signal.
EDIT Now the question made it clear, that the signalling takes place within one JVM. For this signals are definitely the wrong thing in Java.
So the simplest solution is to create and start the second thread directly from within the first thread. No signalling required.
The next best solution is to code a "rendezvous point" using Object.wait() in the second thread (using any object instance but the Thread itself) and Object.notify() or notifyAll() from the first thread. Searching for these terms in a Java tutorial will bring up enough examples.

Java - how to stop a thread running arbitrary code?

In my application which runs user submitted code[1] in separate threads, there might be some cases where the code might take very long to run or it might even have an infinite loop! In that case how do I stop that particular thread?
I'm not in control of the user code, so I cannot check for Thread.interrupted() from the inside. Nor can I use Thread.stop() carelessly. I also cannot put those code in separate processes.
So, is there anyway to handle this situation?
[1] I'm using JRuby, and the user code is in ruby.
With the constraints you've provided:
User submitted code you have no control over.
Cannot force checks for Thread.interrupted().
Cannot use Thread.stop().
Cannot put the user code in a process jail.
The answer to your question is "no, there is no way of handling this situation". You've pretty much systematically designed things so that you have zero control over untrusted third-party code. This is ... a suboptimal design.
If you want to be able to handle anything, you're going to have to relax one (or preferably more!) of the above constraints.
Edited to add:
There might be a way around this for you without forcing your clients to change code if that is a(nother) constraint. Launch the Ruby code in another process and use some form of IPC mechanism to do interaction with your main code base. To avoid forcing the Ruby code to suddenly have to be coded to use explicit IPC, drop in a set of proxy objects for your API that do the IPC behind the scenes which themselves call proxy objects in your own server. That way your client code is given the illusion of working inside your server while you jail that code in its own process (which you can ultimately kill -9 as the ultimate sanction should it come to that).
Later you're going to want to wean your clients from the illusion since IPC and native calls are very different and hiding that behind a proxy can be evil, but it's a stopgap you can use while you deprecate APIs and move your clients over to the new APIs.
I'm not sure about the Ruby angle (or of the threading angle) of things here, but if you're running user-submitted code, you had best run it in a separate process rather than in a separate thread of the same process.
Rule number one: Never trust user input. Much less if the input is code!
Cheers
Usually you have a variable to indicate to stop a thread. Some other thread then would set this variable to true. Finally you periodically check, whether the variable is set or not.
But given that you can't change user code , I am afraid there isn't a safe way of doing it.
For Running Thread Thread.Interrupt wont actually stop as sfussenegger mentioned aforth (thanks sfussenegger recollected after reading spec).
using a shared variable to signal that it should stop what it is doing. The thread should check the variable periodically,(ex : use a while loop ) and exit in an orderly manner.
private boolean isExit= false;
public void beforeExit() {
isExit= true;
}
public void run() {
while (!isExit) {
}
}

Categories

Resources