Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Can't kill QProcess in overriden closeEvent()
QtWS25 Last Chance

Can't kill QProcess in overriden closeEvent()

Scheduled Pinned Locked Moved Unsolved General and Desktop
qprocessqcloseevent
12 Posts 4 Posters 2.3k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • N Offline
    N Offline
    nikko1991
    wrote on last edited by
    #1

    Hello all,

    I'm facing troubles to close a program started with QProcess. The problem seems to be that I wan't to kill the process after I have pressed the exit button. So in other words I attempt to kill the process in overridden QcloseEvent function. the kill() command won't kill the process for some reason. I tested that kill() works fine, if I do it in another function before closing the GUI app.

    Could someone advice me how can I kil() the process properly when exiting the GUI? I'm newbie Qt and rather novice in C++ also.

    Here is my implementation of the app

    The ui header file where I override the QCloseEvent and initialize the Qprocess pointer

    class Ui_MainWindow :public QMainWindow
    {
    protected:
       void closeEvent (QCloseEvent *event) override;
    
    public:
        QWidget *centralwidget;
        QFrame *frame;
    ...
        QProcess *scanProcess;
    ...
    
    

    Here is the method where start the process:

    void Ui_MainWindow::start_scan(){
    
            std::cout << "rosrun point_collector collector " << scantime->text().toStdString() << " " << savepath->text().toStdString() << std::endl;
            QString str = "rosrun point_collector collector "+ scantime->text()+" "+savepath->text()+" "+"lidar/lidar"+" "+"lidar_frame"+" "+"worksite";
            scanProcess->setProcessChannelMode(QProcess::MergedChannels);
            scanProcess->start(str);
            bool started = scanProcess->waitForStarted(1000);
            std::cout << started << " Started" << std::endl;
    }
    

    And the closeEvent implementation:

    void Ui_MainWindow::closeEvent (QCloseEvent *event)
    {
       QMessageBox::StandardButton resBtn = QMessageBox::question( this,tr("box"),
                                    tr("Are you sure?\n"),
                    QMessageBox::Cancel | QMessageBox::No | QMessageBox::Yes,
                    QMessageBox::Yes);
    
        if (resBtn != QMessageBox::Yes) {
            event->ignore();
        }  
        else {
                std::cout << "Scan process running. will be killed" << std::endl;
                //scanProcess->terminate();
                //scanProcess->close();
                 scanProcess->kill();
                 event->accept();
        }
    }
    

    Thanks for tips in advance!

    JonBJ 1 Reply Last reply
    0
    • N nikko1991

      Hello all,

      I'm facing troubles to close a program started with QProcess. The problem seems to be that I wan't to kill the process after I have pressed the exit button. So in other words I attempt to kill the process in overridden QcloseEvent function. the kill() command won't kill the process for some reason. I tested that kill() works fine, if I do it in another function before closing the GUI app.

      Could someone advice me how can I kil() the process properly when exiting the GUI? I'm newbie Qt and rather novice in C++ also.

      Here is my implementation of the app

      The ui header file where I override the QCloseEvent and initialize the Qprocess pointer

      class Ui_MainWindow :public QMainWindow
      {
      protected:
         void closeEvent (QCloseEvent *event) override;
      
      public:
          QWidget *centralwidget;
          QFrame *frame;
      ...
          QProcess *scanProcess;
      ...
      
      

      Here is the method where start the process:

      void Ui_MainWindow::start_scan(){
      
              std::cout << "rosrun point_collector collector " << scantime->text().toStdString() << " " << savepath->text().toStdString() << std::endl;
              QString str = "rosrun point_collector collector "+ scantime->text()+" "+savepath->text()+" "+"lidar/lidar"+" "+"lidar_frame"+" "+"worksite";
              scanProcess->setProcessChannelMode(QProcess::MergedChannels);
              scanProcess->start(str);
              bool started = scanProcess->waitForStarted(1000);
              std::cout << started << " Started" << std::endl;
      }
      

      And the closeEvent implementation:

      void Ui_MainWindow::closeEvent (QCloseEvent *event)
      {
         QMessageBox::StandardButton resBtn = QMessageBox::question( this,tr("box"),
                                      tr("Are you sure?\n"),
                      QMessageBox::Cancel | QMessageBox::No | QMessageBox::Yes,
                      QMessageBox::Yes);
      
          if (resBtn != QMessageBox::Yes) {
              event->ignore();
          }  
          else {
                  std::cout << "Scan process running. will be killed" << std::endl;
                  //scanProcess->terminate();
                  //scanProcess->close();
                   scanProcess->kill();
                   event->accept();
          }
      }
      

      Thanks for tips in advance!

      JonBJ Offline
      JonBJ Offline
      JonB
      wrote on last edited by JonB
      #2

      @nikko1991
      Don't know why kill() works in some places but not others. If you say it does work from other places I can't see why QMainWindow::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 your rosrun.

      Just to verify, try replacing your event->accept(); with event->ignore();, does that somehow make it work?

      You could instead try the kill() in one of QCoreApplication::aboutToQuit() or QGuiApplication::lastWindowClosed(), but these will actually come later, I'd be surprised if they work when from closeEvent() does not....

      1 Reply Last reply
      1
      • N Offline
        N Offline
        nikko1991
        wrote on last edited by
        #3

        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

        JonBJ 1 Reply Last reply
        0
        • N nikko1991

          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

          JonBJ Offline
          JonBJ Offline
          JonB
          wrote on last edited by JonB
          #4

          @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 the kill() you show there will not be called. If this is a problem, I suggested to you earlier that closeEvent() 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 in main() where you exit from QApplication::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 unlike QProcess:start(), QProcess:startDetached() states

          If 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.

          1 Reply Last reply
          0
          • Kent-DorfmanK Offline
            Kent-DorfmanK Offline
            Kent-Dorfman
            wrote on last edited by Kent-Dorfman
            #5

            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.

            1 Reply Last reply
            1
            • N Offline
              N Offline
              nikko1991
              wrote on last edited by
              #6

              @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.

              JonBJ 1 Reply Last reply
              0
              • N nikko1991

                @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.

                JonBJ Offline
                JonBJ Offline
                JonB
                wrote on last edited by
                #7

                @nikko1991
                That's all (terminate/close/kill) the options you have. QProcess::kill() really should be a normal kill. I'd try kill -9 rather than your kill -SIGINT. Running a QProcess.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 than rosrun then that is somehow the issue, which only you can play with.

                1 Reply Last reply
                0
                • SGaistS Offline
                  SGaistS Offline
                  SGaist
                  Lifetime Qt Champion
                  wrote on last edited by
                  #8

                  Hi,

                  Since you are managing a ROS node, can you send a commande to shut it down properly rather than killing it ?

                  Interested in AI ? www.idiap.ch
                  Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                  1 Reply Last reply
                  2
                  • Kent-DorfmanK Offline
                    Kent-DorfmanK Offline
                    Kent-Dorfman
                    wrote on last edited by
                    #9

                    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.

                    JonBJ 1 Reply Last reply
                    0
                    • Kent-DorfmanK Kent-Dorfman

                      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.

                      JonBJ Offline
                      JonBJ Offline
                      JonB
                      wrote on last edited by
                      #10

                      @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!

                      1 Reply Last reply
                      0
                      • N Offline
                        N Offline
                        nikko1991
                        wrote on last edited by
                        #11

                        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!

                        JonBJ 1 Reply Last reply
                        0
                        • N nikko1991

                          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!

                          JonBJ Offline
                          JonBJ Offline
                          JonB
                          wrote on last edited by
                          #12

                          @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 from QProcess available to you, which is how the waitFor()s are implemented anyway. So if you are saying these are causing you problems, don't use them.

                          1 Reply Last reply
                          1

                          • Login

                          • Login or register to search.
                          • First post
                            Last post
                          0
                          • Categories
                          • Recent
                          • Tags
                          • Popular
                          • Users
                          • Groups
                          • Search
                          • Get Qt Extensions
                          • Unsolved