Käseknacker
Käseknacker

Reputation: 271

Terminating QProcess doesn't kill child process

I have the following Problem: I have a Qt GUI-Application (c++) which starts an external java application via a bash-script. When I terminate my QProcess the script is killed, but the child-process (the java-application) is still running.

I don't understand this behavior, because if I run the script in terminal and kill it, the child process is also killed. Maybe it has something to do with the various event loops in Qt, which I have not understood yet.


Here is my code:

MainWindow.h

#include <QMainWindow>
#include <QProcess>

namespace Ui {
  class MainWindow;
}

class MainWindow : public QMainWindow
{
  Q_OBJECT
public:
  explicit MainWindow(QWidget *parent = nullptr);
  ~MainWindow();

private slots:
  void slot_startQProcess();
  void slot_killQProcess();

private:
  Ui::MainWindow *ui;

  QProcess myProcess;
};

MainWindow.cpp

#include "MainWindow.h"
#include "ui_MainWindow.h"

MainWindow::MainWindow(QWidget *parent) :
  QMainWindow(parent),
  ui(new Ui::MainWindow)
{
  ui->setupUi(this);
  connect(ui->pb_start, &QPushButton::clicked, this, &MainWindow::slot_startQProcess);
  connect(ui->pb_kill, &QPushButton::clicked, this, &MainWindow::slot_killQProcess);
}

MainWindow::~MainWindow()
{
  delete ui;
}

void MainWindow::slot_startQProcess()
{
  myProcess.setWorkingDirectory("./i2exrep");
  myProcess.start("./myScript.sh");
}

void MainWindow::slot_killQProcess()
{
  myProcess.close();
}

main.cpp

#include "MainWindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
  QApplication a(argc, argv);
  MainWindow w;
  w.show();
  return a.exec();
}

myScript.sh

#!/bin/csh
java -jar i2exrep.jar

Folder structure:


So my application starts "myScript.sh" which starts "java -jar i2exrep.jar"

Killing the QProcess only terminates "myScript.sh", but "java -jar i2exrep.jar" is still running. - i2exrep.jar


EDIT:

I tried the same with another main function:

#include <QCoreApplication>
#include <QProcess>
int main(int argc, char *argv[])
{
  QCoreApplication a(argc, argv);
  QProcess myProcess;
  myProcess.setWorkingDirectory("./i2exrep");
  myProcess.start("./myScript.sh");
  return a.exec();
}

When I quit this program, then the Java application is also terminated. When I finish the first program (the GUI application), then only the script is terminated and the Java application continues to run. I get the following error message:

QProcess: Destroyed while process ("./myScript.sh") is still running.

Upvotes: 1

Views: 1793

Answers (2)

Marcofrk
Marcofrk

Reputation: 11

I solved it by using setsid to start the process.

Please, check the example below:

process->start("setsid ./example.sh");
(...)
QString killingProcess = "kill -TERM -" + QString::number(process->pid());
system(killingProcess.toStdString().c_str());

For more details, please, visit this link.

Upvotes: 1

Oleg Andriyanov
Oleg Andriyanov

Reputation: 5289

I assume you run some UNIX system (since the shell and / path separator).

Do you really need both processes (the shell and java)? Maybe leaving only java will solve your problem. Add exec to your script:

#!/bin/csh
exec java -jar i2exrep.jar

My guess is that when you run your application in a terminal and then close it, all child processes receive SIGHUP since they lose the controlling terminal. When you run the script from GUI application there is no controlling terminal at the first place, so java won't terminate on quit. Anyway, the correct way to terminate a child process is to send it a signal (SIGTERM, maybe SIGKILL after some time) and then wait(2) it's termination.

If you don't want to get rid from a shell process in your process chain, see this answer to find out how to forward signals to child process in shell.

Upvotes: 1

Related Questions