如何确定在 Linux 上使用 Qt4 终止 QProcess 的信号?

Posted

技术标签:

【中文标题】如何确定在 Linux 上使用 Qt4 终止 QProcess 的信号?【英文标题】:How to determine the signal that terminated a QProcess with Qt4 on Linux? 【发布时间】:2020-09-04 17:56:27 【问题描述】:

我想检测我启动的QProcess 是否被SIGKILLSIGTERM 外部终止。当我编写自己启动的进程时,这对于区分崩溃(错误)和外部干扰非常重要。

我尝试通过连接到QProcess::started 的插槽注册被监视的进程并设置SIGCHLD 处理程序(使用sigaction)以使用waitpid 捕获进程状态。问题是waitpid 清除了内部内核数据结构,即使我正确地将我的处理程序链接到QProcess 实现上的那个,后者也无法获得子状态,因为任何下一次调用waitpid对于那个 pid 失败。将进程状态设置为QProcess::ProcessState::NotRunningQProcess::setProcessState 通常可以避免挂起对waitForFinished 的调用,但有些极端情况我还无法修复。

我想知道除了修改 Qt 的源代码以将状态信息存储在某处之外,是否没有更好的方法。

注意:我知道崩溃也会以SIGABRT 的信号终止。这里的主要问题是SIGKILL 可能会告诉我 Linux 中的内存不足杀手是导致进程终止的原因。

【问题讨论】:

【参考方案1】:

这是我的代码,朋友。

QProcess* pExe = new QProcess(this);
connect(pExe, SIGNAL(finished(int, QProcess::ExitStatus)), this,  SLOT(onOSRExit(int, QProcess::ExitStatus)));
pExe->setWorkingDirectory(QCoreApplication::applicationDirPath());
pExe->start("some.exe");

....

void CXXXXX::onOSRExit(int exitCode, QProcess::ExitStatus exitStatus)


【讨论】:

谢谢,但这并不能解决问题。在 Linux 下,我没有收到杀死 exitCode 进程的信号。【参考方案2】:

Qt 4下修改Qt代码的解决方案,基本上就是对QProcessPrivate::waitForDeadChild()的简单修改:

if (qt_safe_waitpid(pid_t(pid), &exitStatus, WNOHANG) > 0) 
         processManager()->remove(q);
         crashed = !WIFEXITED(exitStatus);
-        exitCode = WEXITSTATUS(exitStatus);
+        exitCode = crashed ? WTERMSIG(exitStatus) : WEXITSTATUS(exitStatus);

在发出QProcess::finished() 之后,该信号将在QProcess::exitCode() 上可用。

注意:Qt5 使用的是 Thiago Macieira 的forkfd,所以这个解决方案不起作用。

【讨论】:

以上是关于如何确定在 Linux 上使用 Qt4 终止 QProcess 的信号?的主要内容,如果未能解决你的问题,请参考以下文章

如何用qt4编程结束linux进程

如何使用自制软件在 macOS 上安装 qt4?

如何用CMD命令终止和启动进程?

如何确定客户端连接是不是在 Java 服务器的 TCP 套接字连接中终止?

如何在 Linux 中存储不同编译的相同库版本?

Linux中怎么终止正在运行的后台程序