I am creating a process P1 by using Process P1= Runtime.exec(...). My process P1 is creating another process say P2, P3....
Then I want to kill process P1 and all the processes created by P1 i.e. P2, P3...
P1.destroy() is killing P1 only, not its sub processes.
I also Googled it and found it's a Java bug:
http://bugs.sun.com/view_bug.do?bug_id=4770092
Does anyone have any ideas on how to do it?
Yes, it is a Bug, but if you read the evaluation the underlying problem is that it is next to impossible to implement "kill all the little children" on Windows.
The answer is that P1 needs to be responsible for doing its own tidy-up.
I had a similar issue where I started a PowerShell Process which started a Ping Process, and when I stopped my Java Application the PowerShell Process would die (I would use Process.destroy() to kill it) but the Ping Process it created wouldn't.
After messing around with it this method was able to do the trick:
private void stopProcess(Process process) {
process.descendants().forEach(new Consumer<ProcessHandle>() {
#Override
public void accept(ProcessHandle t) {
t.destroy();
}
});
process.destroy();
}
It kills the given Process and all of its sub-processes.
PS: You need Java 9 to use the Process.descendants() method.
Java does not expose any information on process grandchildren with good reason. If your child process starts another process then it is up to the child process to manage them.
I would suggest either
Refactoring your design so that your parent creates/controls all child processes, or
Using operating system commands to destroy processes, or
Using another mechanism of control like some form of Inter-Process Communication (there are plenty of Java libraries out there designed for this).
Props to #Giacomo for suggesting the IPC before me.
Is you writing other processes' code or they are something you cannot change?
If you can, I would consider modifying them so that they accept some kind of messages (even through standard streams) so they nicely terminate upon request, terminating children if they have, on their own.
I don't find that "destroying process" something clean.
if it is bug, as you say then you must keep track pf process tree of child process and kill all child process from tree when you want to kill parent process
you need to use data structure tree for that, if you have only couple of process than use list
Because the Runtime.exec() return a instance of Process, you can use some array to store their reference and kill them later by Process.destroy().
Related
Hello !
I would like to create a child process which could run after the end of the main process in java (I did a simple schema of the execution I'd like : result wanted. Is that possible ?
You can't start a child process from a process that is no longer running, so the child will have to be started beforehand. And in that case, how will the child know the parent has terminated?
Your design is upside down. The "main work" should be done in a child, and the parent should sit there waiting for the child to terminate before it does whatever it needs to do. That's an easy implementation and is a common design pattern. It is, for example, what any Unix shell does to run an external program.
(I assume that when you say "process" that is what you mean - i.e., something in an entirely separate address space)
Finally I've found a simple response. I don't know why I was hesitating so much.
I'd just start a thread from my main fonction and according to my log, the thread continued after the principal treatment.
I'm guessing I have a daemon thread because the child is not killed.
Is it possible to create an instance of Process class if I have pid of process which already running? And put this Process in Map processMap. And then be able to stop Processes or check IsAlive
This isn't what Process is for:
Process provides control of native processes started by ProcessBuilder.start and Runtime.exec.
That's not to say you can't control already-running processes from Java; it's just that Process isn't the thing you should use to do it.
You can make your own class to do what you say you need, e.g:
interface ExternalProcess {
boolean isRunning();
void kill();
}
with implementations of the methods such as:
Verify if a process is running using its PID in JAVA
Killing a process in Java
First, to shortly describe my problem. Based on the simbad simulator ( http://simbad.sourceforge.net/doc.php - not important for my question ), I want to build a system that deploys rovers which will explore the environment. The idea is that these rovers will avoid obstacles in the environment as well as other rovers. Let's call this a simulation.
The main elements in this simulation are of course the rovers, the environment, and a central station which will control the rovers and also send commands to it. This will run on a thread.
What I would like to have, is on another thread/process, to have a listener. This will listen to commands inputted from the keyboard and translate them into commands that will be applied in my simulation by the central station.
For example, each rover might have an ID, and I might want to remove a remover based on its id. Then I'd like to write something like: remove rover 1, the listener that is running on another thread maps this to a command and for example calls the function centralStation.removeRobot(id_of_robot).
What is the best way of implementing this ? Basically I will have 2 threads, one running the simulation, one listening to commands, and the centralStation should be a shared resource ? How do I make it a shared resource (make a main, initiate the central station, then call the other 2 threads to start doing their job? ) ?
I was wondering what the best practices for this is, and how to make it as simple as possible.
Thank you :)
A simple solution is to simply put an appropriate data structure "between" your components.
For example an instance of ConcurrentLinkedQueue. The idea here: your "input" thread writes "command" objects into that queue; and the other thread looks into that queue, and when it finds a new command, that is "applied" to the simulation.
The important aspect is: you really do not want that two threads are operating on the same data somehow.
Well how about Java Exchanger, where String is the id of rover/command that your listener would transfer to central station
https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Exchanger.html
If I am understanding it correct then you want to start the system and at runtime pass the rover id/command, after processing it via a Listener(which would be in a separate thread), to the central station(which would be in a separate thread).
So how I might have proceeded with this would be:
In main thread, start the simulator, Create an Exchanger, and start two threads, one for central station and another for listener.
// pseudocode for main
main() {
// start simulator ( I am not sure what this thing is)
Exchanger<String> exc = new Exchanger<String>();
new CentralStationThread(exc);
new CommandListenerThread(exc);
}
Now in CentralStationThread one of the first thing that you might wanna do is register with the listener
//pseudocode for run method of central station
public void run(){
String roverIdToStop = exc.exchange(new String);
// some code to trigger the rover stop
// send in replacement rover
}
And something similar in CommandListenerThread thread, but not at start
//pseudocode for run method of listener
public void run(){
// Listen to keyboard
// String roverIdOrCommand = Parse the command & make something out out it
// when the command is ready to be sent to central station do following
String roverIdToStop = exc.exchange(roverIdOrCommand);
// keep looking for further commands
}
I agree, There might me several ways to achieve the same but this is what came to my mind. Hope it helps !
I am running a local BrowerStack test, for which I must instantiate a connection with the local server and BrowserStack. The instructions for this type of test are found here.
I am trying to declare the process to a variable
Process serverConnection = new ProcessBuilder("C:\\Users\\folder\\BrowserStackLocal.exe","**Password**", serverURL + ",80").start();
Looking at the task manager, I see that this line creates two BrowserStackLocal.exe processes, which I think is due to how they manage logging in. Is there a way I can reference the second BrowserStackLocal.exe process?
In my cleanup I call
serverConnection.destroy();
But this only ends one of the processes. Right now I also call
Runtime.getRuntime().exec("taskkill /F /IM BrowserStackLocal.exe");
Which successfully ends the other instance, but I would much prefer to hold a reference and call .destroy().
Any suggestions for how to accomplish this would be greatly appreciated.
EDIT: I am almost sure that the reason for the two processes is the logging in functionality, as when I call the wrong password only one window opens. The second process appears to be the one doing all the computing based on its CPU usage.
EDIT 2: Further testing with BrowserStackLocal confirms that it is the process of logging in which creates an additional process. A solution could identify a way to trace the instantiation of this second process from the first process.
Edit 3: The processes appear to be linked, as when I exit one of them from the task manager, sometimes the other one will close automatically.
Turns out that is how BrowserStack handles the login process, and its unavoidable.
I am calling a .exe file from my java code using :
Runtime r=Runtime.getRuntime();
Process p=null;
p=r.exec("ABCD.exe");
I want the program to wait till the exe completes its job .(This is actually server side code...control passes to Client side after this).The problem now is that UI on client side is populated before the .exe on server side can form the required components.Hence UI formed does not have the correct files.
I have tried the normal p.waitfor() thing but it doesn't seem to work.
Any suggestions?
The short answer is that you want to call Process.waitFor() in your main thread, as you allude to.
However, dealing with Processes is not exactly fire-and-forget, because, as referenced by the class javadocs, you likely need to be reading the process' output. If you don't do this (which in this case will require a separate thread) then in many instances you'll have an effective deadlock - your Java app is waiting for the process to finish, but the process is trying to write output to a full buffer and thus waiting for the Java app to read its output.
If you gave more information about how "it didn't work", that would help with the diagnosis too.
Edit: on a completely separate point, there's no purpose in initialising p to null and then immediately reassigning it. Your second line would be clearer and less confusing as Process p = r.exec("ABCD.exe");.