Can't stop a process
-
Hi,
I am using QProcess to launch a .exe process in Windows, lets say db.exe. This db.exe program launches another process, a java.exe process.
process->start("db.exe", QStringList() << "");
It runs the db.exe and then java.exe properly.
However, when I try to terminate the process gracefully, it doesn't work. Soprocess->terminate()
does nothing.
If I doprocess->kill()
it kills the db.exe process, but leaving java.exe alive.If I run the db.exe program by command line, I can stop it with
ctrl+c
(it closes both proceses), but I don't know how to send that signal using QProcess.
I don't have any control over the db.exe application (so I can't modify it.)I have a lot of other functionalities relaying on QProcess, so I don't want to start processes without it.
Any idea? -
Hi @enekow
Its not recommended to kill process from another process. A process should be killed gracefully by itself or by system.
Its recommended to communicate between process using IPC.
Start Process2 from Process1. Communicate to Process2 from Process1 using IPC and kill Process2 gracefully. -
Thanks for your responses :)
@SGaist said in Can't stop a process:
One possibility would be to call taskkill from another QProcess.
I'll try that way, because I dont find another way. However, the only way I have to identify the java.exe process is by name. And it doesn't seems very clever to kill all processes called java.exe.
@yuvaram said in Can't stop a process:
Its not recommended to kill process from another process. A process should be killed gracefully by itself or by system.
Its recommended to communicate between process using IPC.
Start Process2 from Process1. Communicate to Process2 from Process1 using IPC and kill Process2 gracefully.That is what I am trying to do... but I cannot modify Process1 to change its behavior. I launch Process1 and this process launches the Process2 automatically. The only way to communicate with Process2 through Process1 is sending
ctrl+c
signal to Process1. -
You can get the process id using QProcess::processId.
-
@enekow
This in itself has nothing to do with Qt. It's to do with how processes work under the OS.You need either to find parent process IDs (certainly under Linux, not sure how that works under Windows), or possibly send a
signal(SIGINT)
todb.exe
to replicate theCtrl+C
which you say works --- though that might work from terminal only, depending on how it's been written. -
-
@enekow
No toQProcess
"sendingCtrl+C
".Have a look at https://stackoverflow.com/questions/27771843/whats-the-difference-between-qprocesskill-and-qprocessterminate
"Under Windows
terminate()
sendsWM_CLOSE
window message" means it'll be useless for console applications:Console applications on Windows that do not run an event loop, or whose event loop does not handle the WM_CLOSE message, can only be terminated by calling kill().
I think you need to do something like the following (from http://www.qtcentre.org/threads/36911-Can-t-send-a-Ctrl-C-to-a-QProcess-(Win32)):
Default Re: Can't send a Ctrl-C to a QProcess (Win32)
Sorry, yes, Ctrl+C is SIGINT. Nevertheless using terminate() is the way to go. Unfortunately console applications don't support being killed by terminate(). What you can do is try to send the SIGINT signal yourself to the other process using ::kill() (your system should support it).Or also there:
Sorry for the late entrance, but it would seem this is still a valid discussion. I have just solved the problem under Windows 7 with Qt5 by closing the stream to stdin of the child process. I.e. process->close() instead of process->terminate(). The child process was then gracefully able to shut down.
though note the latter may or may not work.
-
Thanks for your help @JonB
However I already try those options with no result. I think it could work with
GenerateConsoleCtrlEvent
(WINAPI) but it sends the event to an entire group of processes (including the main process). Maybe creating the processes detached could work, but not an option for me.I think I found the way to go. In windows there is a tool called
wmic
.wmic process where (ParentProcessId="Process1_PID") get ProcessId
This command will return all children pids. Then, I can
taskkill
using the pids.
It isn't a very elegant elegant way, but I don't have much options.Thank you all :D