[英]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. 我有以下问题:我有一个Qt GUI应用程序(c ++),它可以通过bash脚本启动外部Java应用程序。 When I terminate my QProcess the script is killed, but the child-process (the java-application) is still running.
当我终止QProcess时,脚本被杀死,但是子进程(java应用程序)仍在运行。
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.
也许这与Qt中的各种事件循环有关,但我还不了解。
Here is my code: 这是我的代码:
MainWindow.h 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 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 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 myScript.sh
#!/bin/csh
java -jar i2exrep.jar
Folder structure: 资料夹结构:
So my application starts "myScript.sh" which starts "java -jar i2exrep.jar" 所以我的应用程序启动了“ myScript.sh”,启动了“ java -jar i2exrep.jar”
Killing the QProcess only terminates "myScript.sh", but "java -jar i2exrep.jar" is still running. 杀死QProcess只会终止“ myScript.sh”,但“ java -jar i2exrep.jar”仍在运行。 - i2exrep.jar
-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. 当我退出该程序时,Java应用程序也将终止。 When I finish the first program (the GUI application), then only the script is terminated and the Java application continues to run.
当我完成第一个程序(GUI应用程序)时,只有脚本终止并且Java应用程序继续运行。 I get the following error message:
我收到以下错误消息:
QProcess: Destroyed while process ("./myScript.sh") is still running.
I assume you run some UNIX system (since the shell and /
path separator). 我假设您运行了一些UNIX系统(由于shell和
/
路径分隔符)。
Do you really need both processes (the shell and java)? 您是否真的需要两个进程(shell和Java)? Maybe leaving only java will solve your problem.
也许只留下java将解决您的问题。 Add
exec
to your script: 将
exec
添加到脚本中:
#!/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. 我的猜测是,当您在终端中运行应用程序然后关闭它时,所有子进程都会收到SIGHUP,因为它们失去了控制终端。 When you run the script from GUI application there is no controlling terminal at the first place, so java won't terminate on quit.
从GUI应用程序运行脚本时,首先没有控制终端,因此Java不会在退出时终止。 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.
无论如何,终止子进程的正确方法是向其发送信号(SIGTERM,或者一段时间后可能是SIGKILL),然后等待其终止(2)。
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. 如果您不想摆脱流程链中的Shell流程,请查看此答案以了解如何将信号转发到Shell中的子流程。
I solved it by using setsid
to start the process. 我通过使用
setsid
来启动进程来解决了。
Please, check the example below: 请检查以下示例:
process->start("setsid ./example.sh");
(...)
QString killingProcess = "kill -TERM -" + QString::number(process->pid());
system(killingProcess.toStdString().c_str());
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.