QProcess::kill() 不会在 linux 中杀死 children
QProcess::kill() does not kill children in linux
我使用 QProcess
在服务器上进行冗长的计算。它可能只需要几秒钟或最多几个小时,只要我让它自己完成就可以正常工作。但是,我需要有可能在它完成之前终止进程,这只在我的 windows 机器上工作正常。
在linux中,我的QProcess
被杀死,我的数据处理成功执行,但它产生的child进程仍然存在。这是我的代码的摘录:
// constructor
server::server(QObject* parent) : QTcpServer(parent)
{
this->calc_proc = new QProcess(this);
QObject::connect(this->calc_proc, SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(calc_finished(int,QProcess::ExitStatus)));
...
}
void server::start_job(){
QString working_directory = "...";
QString input_file = "...";
QStringList arguments;
arguments << "memory=max" << "batch=no" << input_file;
this->calc_proc->setWorkingDirectory(working_directory);
this->calc_proc->start("path_to_external_program", arguments);
qDebug() << "Calc started with pid: " << this->calc_proc->pid();
}
void server::kill_job(){
this->calc_proc->terminate();
//this->calc_proc->kill();
}
使用 terminate()
或 kill()
时,行为似乎没有什么不同。据我所知,child 个流程是 children 个流程:
Calc started with pid: 26395
ps ax
...
26441 pts/0 S 0:00 time /msc/MSC_Nastran/20131/msc20131/linux64/analysis
26442 pts/0 Rl 16:59 /msc/MSC_Nastran/20131/msc20131/linux64/analysis
...
ps -p 26442 -o ppid=
26441
ps -p 26441 -o ppid=
26395
我的 QProcess
returns 他的 pid 为 26395 有一个 child 26441 有一个 child 26442。所以我希望所有这些都被杀死当我杀了我的。如前所述,他们幸存下来。有什么 platform-independent 方法可以杀死它们吗?
QProcess::kill()
就是 SIGKILL
。所以说的不是Qt,而是Unix进程管理。
你可以阅读那个问题How to make child process die after parent exits?
user4419802 让我走上了正确的轨道。在 Linux 中,终止进程不会终止其 children。他们向上移动并继续,不再有 parent。
一般来说,你会想在生成它们时保存所有 pids
的 children(并且有多个答案告诉你如何这样做)但在我的情况下这是不可能的,因为我没有生成 children,但我调用的外部应用程序是在我不知情的情况下生成的。所以我想出了以下对我有用的解决方案:
QProcess* main_process = new QProcess(this);
...
// linux: a child is spawned which is not killed with its parent
// therefore the process id is retrieved and the process killed independently
#if defined(Q_OS_LINUX)
QProcess get_child_a;
QStringList get_child_a_cmd;
get_child_a_cmd << "--ppid" << QString::number(main_process->processId()) << "-o" << "pid" << "--no-heading";
get_child_a.start("ps", get_child_a_cmd);
get_child_a.waitForFinished(5000);
QString child_a_str = get_child_a.readAllStandardOutput();
int child_a = child_a_str.toInt();
QProcess::execute("kill " + QString::number(child_a));
#endif
// windows & linux: kill main process
main_process->kill();
在我的例子中,我知道只返回一个 child 进程 ID,因此 get_child
进程输出的解析是一个简单的转换。
感谢@Bowdzone 的初步想法!
由于我的父进程产生了多个子进程,所以答案对我来说并不是 100% 有效,所以我对这种方法进行了一些调整:
void CameraReceiver::stopChildProcesses(qint64 parentProcessId) {
qDebug() << "stopChildProcesses for parent id:" << parentProcessId;
QProcess get_childs;
QStringList get_childs_cmd;
get_childs_cmd << "--ppid" << QString::number(parentProcessId) << "-o" << "pid" << "--no-heading";
get_childs.start("ps", get_childs_cmd);
get_childs.waitForFinished();
QString childIds(get_childs.readAllStandardOutput());
childIds.replace('\n', ' ');
QProcess::execute("kill " + childIds);
}
然后我可以简单地调用以下内容:
stopChildProcesses(parentProcess.processId());
我使用 QProcess
在服务器上进行冗长的计算。它可能只需要几秒钟或最多几个小时,只要我让它自己完成就可以正常工作。但是,我需要有可能在它完成之前终止进程,这只在我的 windows 机器上工作正常。
在linux中,我的QProcess
被杀死,我的数据处理成功执行,但它产生的child进程仍然存在。这是我的代码的摘录:
// constructor
server::server(QObject* parent) : QTcpServer(parent)
{
this->calc_proc = new QProcess(this);
QObject::connect(this->calc_proc, SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(calc_finished(int,QProcess::ExitStatus)));
...
}
void server::start_job(){
QString working_directory = "...";
QString input_file = "...";
QStringList arguments;
arguments << "memory=max" << "batch=no" << input_file;
this->calc_proc->setWorkingDirectory(working_directory);
this->calc_proc->start("path_to_external_program", arguments);
qDebug() << "Calc started with pid: " << this->calc_proc->pid();
}
void server::kill_job(){
this->calc_proc->terminate();
//this->calc_proc->kill();
}
使用 terminate()
或 kill()
时,行为似乎没有什么不同。据我所知,child 个流程是 children 个流程:
Calc started with pid: 26395
ps ax
...
26441 pts/0 S 0:00 time /msc/MSC_Nastran/20131/msc20131/linux64/analysis
26442 pts/0 Rl 16:59 /msc/MSC_Nastran/20131/msc20131/linux64/analysis
...
ps -p 26442 -o ppid=
26441
ps -p 26441 -o ppid=
26395
我的 QProcess
returns 他的 pid 为 26395 有一个 child 26441 有一个 child 26442。所以我希望所有这些都被杀死当我杀了我的。如前所述,他们幸存下来。有什么 platform-independent 方法可以杀死它们吗?
QProcess::kill()
就是 SIGKILL
。所以说的不是Qt,而是Unix进程管理。
你可以阅读那个问题How to make child process die after parent exits?
user4419802 让我走上了正确的轨道。在 Linux 中,终止进程不会终止其 children。他们向上移动并继续,不再有 parent。
一般来说,你会想在生成它们时保存所有 pids
的 children(并且有多个答案告诉你如何这样做)但在我的情况下这是不可能的,因为我没有生成 children,但我调用的外部应用程序是在我不知情的情况下生成的。所以我想出了以下对我有用的解决方案:
QProcess* main_process = new QProcess(this);
...
// linux: a child is spawned which is not killed with its parent
// therefore the process id is retrieved and the process killed independently
#if defined(Q_OS_LINUX)
QProcess get_child_a;
QStringList get_child_a_cmd;
get_child_a_cmd << "--ppid" << QString::number(main_process->processId()) << "-o" << "pid" << "--no-heading";
get_child_a.start("ps", get_child_a_cmd);
get_child_a.waitForFinished(5000);
QString child_a_str = get_child_a.readAllStandardOutput();
int child_a = child_a_str.toInt();
QProcess::execute("kill " + QString::number(child_a));
#endif
// windows & linux: kill main process
main_process->kill();
在我的例子中,我知道只返回一个 child 进程 ID,因此 get_child
进程输出的解析是一个简单的转换。
感谢@Bowdzone 的初步想法!
由于我的父进程产生了多个子进程,所以答案对我来说并不是 100% 有效,所以我对这种方法进行了一些调整:
void CameraReceiver::stopChildProcesses(qint64 parentProcessId) {
qDebug() << "stopChildProcesses for parent id:" << parentProcessId;
QProcess get_childs;
QStringList get_childs_cmd;
get_childs_cmd << "--ppid" << QString::number(parentProcessId) << "-o" << "pid" << "--no-heading";
get_childs.start("ps", get_childs_cmd);
get_childs.waitForFinished();
QString childIds(get_childs.readAllStandardOutput());
childIds.replace('\n', ' ');
QProcess::execute("kill " + childIds);
}
然后我可以简单地调用以下内容:
stopChildProcesses(parentProcess.processId());