Can't kill QProcess in overriden closeEvent()
-
@nikko1991
Don't know whykill()
works in some places but not others. If you say it does work from other places I can't see whyQMainWindow::closeEvent()
would not work, it really should be fine/not be relevant from there. If it were me I would check again! And test with some command other than yourrosrun
.Just to verify, try replacing your
event->accept();
withevent->ignore();
, does that somehow make it work?You could instead try the
kill()
in one ofQCoreApplication::aboutToQuit()
orQGuiApplication::lastWindowClosed()
, but these will actually come later, I'd be surprised if they work when fromcloseEvent()
does not.... -
Thanks for such a fast reply @JonB !
I see now that the problem seem to be connected with ROS (rosrun). If I wait for too long (1-2 sec) Qprocess some how loses my rosnode and is not able to kill it anymore. Although it claims that the process is killed. By coding start() and kill() after another killing is sucesfull. Otherwise not..
I tested this with gnome-calculator. I was able to kill and also terminate the calculator in the closeEvent() function. Or the class destructor killed it. Im not 100% sure, but I feel that somehow the class destruction of my UI_MainWindow may bypass my actions in the closeEvent(). Is this possible?
Anyway, as I undestand my rosnode should also be killed in the class destructor where I delete the QProcess object. Even if would not kill() "manually"..
So, I ques I need to move back for ROS forums..
Tips and ideas are still welcome here too!
Thanks
Nikko -
@nikko1991 said in Can't kill QProcess in overriden closeEvent():
somehow the class destruction of my UI_MainWindow may bypass my actions in the closeEvent(). Is this possible?
I don't know what this means. If, for whatever reason, your
Ui_MainWindow::closeEvent()
is not executed then thekill()
you show there will not be called. If this is a problem, I suggested to you earlier thatcloseEvent()
might not be the best place to be killing a subprocess and gave you a couple of alternatives. Or perhaps in a destructor, or back inmain()
where you exit fromQApplication::exec()
, might be better.Having said this, maybe the whole thing is not necessary. It's not terribly clear from the documentation, but assuming you are using
QProcess:start()
to run your subprocess it may be terminated on exiting your application anyway. Because unlikeQProcess:start()
,QProcess:startDetached()
statesIf the calling process exits, the detached process will continue to run unaffected.
which implies to me that they expect non-detached processes to be terminated. You would have to investigate.
You will also have to investigate the behaviour of your
rosrun
executable. Applications can do various things to avoid/ignore certain kinds of killing. -
Nevermind. I read this as threading related, not processes...apples and oranges.
In general it is considered bad to kill() a thread, so many threading libraries don't have the option. A better approach is to set an event flag to tell the thread to exist gracefully and allow the thread to do its cleanup if necessary.
-
@JonB
I tried to do killing trough QApplication::aboutToQuit() and QApplication::lastWindowClosed() signals. They did not work out.I also tried killing the process with various ways in my UI destructor without luck.
Tried to kill this process with another QProcess.start("rosnode kill point_collector") that is one way of killing my node in ROS. No luck. "rosnode kill point_collector" works fine in terminal (in any directory) although I start the node with Qprocess in my UI.
Also QProcess.start("kill -SIGINT " + QString::number(scanProcess->processId()) did not work out.@Kent-Dorfman
Do I have other options than Qprocess.terminate() or QProcess.close() instead of kill()? I have tried those.I will keep investigating. Thanks for tips again.
-
@nikko1991
That's all (terminate/close/kill) the options you have.QProcess::kill()
really should be a normal kill. I'd trykill -9
rather than yourkill -SIGINT
. Running aQProcess.start("kill ...
really is the same as doing it in a terminal. You'll have to try to figure what's going on: if these things work against a program other thanrosrun
then that is somehow the issue, which only you can play with. -
Hi,
Since you are managing a ROS node, can you send a commande to shut it down properly rather than killing it ?
-
yes. if you are on a posix system then send the kill via a signal instead of invoking yet another process call.
assuming you know the process pid then
SYNOPSIS #include <sys/types.h> #include <signal.h> int kill(pid_t pid, int sig); Feature Test Macro Requirements for glibc (see feature_test_macros(7)): kill(): _POSIX_C_SOURCE
The concern would be that the qprocess kill makes that exact same call so if it isn't dieing using the native Qt call then something more sinister is going on.
-
@Kent-Dorfman said in Can't kill QProcess in overriden closeEvent():
The concern would be that the qprocess kill makes that exact same call so if it isn't dieing using the native Qt call then something more sinister is going on.
I concur!
-
Found the solution.
So I investigated and found out that my rosnode gets the SIGINT signal, but fails when my SIGINT handler calls ros::shutdown() that is a way to shutdown ROS. This should indicate to my loop that is time to stop. This should be a proper way to shutdown @SGaist @Kent-Dorfman @JonB . So, I replaced the ros::shutdown() with setting a global boolean variable and monitoring it in my loop. And now my program works atleast with kill(pid,SIGINT) call and it should work also with QProcess.start(kill -SIGINT pid).
Here is my answer I posted on ROS forums: https://answers.ros.org/question/369343/how-to-kill-rosnode-via-qt-gui-qprocess-node-hungs/?answer=369888#post-id-369888
I believe shutting down ROS from Qt/other program is slower than from terminal and these delays may cause some strange things for ROS. waitforStarted(-1) and waitForFinished(-1) won't notice this because the program commanded starts, but the roscore started by the program is the slowing one. I don't know if this makes sense, but I was able to make similar hang of my node in terminal by starting the node and hitting Ctrl+c right after.
Also, if the shutdown takes some time, My Qt gui's QProcess destructor may try to kill() the process (as it is already exiting) and cause some more troubles for ROS.Thank you for your advises very much!
-
@nikko1991 said in Can't kill QProcess in overriden closeEvent():
I believe shutting down ROS from Qt/other program is slower than from terminal
I don't claim to understand what you are saying in your post, and I probably won't understand even if you try to explain more! But I do not know what you could mean by this sentence. The "terminal" (i.e. a "shell") simply is "from other program". There is no difference between a shell and any other program under Linux, and if you can do something from a shell you can do it from a program you write.
As a separate matter, I wouldn't use the blocking
QProcess::waitFor...()
methods anyway, at least not in the case of issues with the program spawned. There is no need to, as there are the asynchronous signals fromQProcess
available to you, which is how thewaitFor()
s are implemented anyway. So if you are saying these are causing you problems, don't use them.