Reputation: 91
I want to detect the QProcess
I launched was terminated externally by either SIGKILL
or SIGTERM
. This is important in distinguishing between a crash (bug) and an external interference when I've written the process I'm launching myself.
I've tried registering watched processes through a slot connected to QProcess::started
and setting a SIGCHLD
handler (using sigaction
) to capture the process status using waitpid
. The issue is that waitpid
clears the internal kernel data structure and even if I properly chain my handler to the one on the QProcess
implementation, the latter isn't able to get the child status as any next calls to waitpid
for that pid fail. Setting the process state to QProcess::ProcessState::NotRunning
through QProcess::setProcessState
avoids hanging on calls to waitForFinished
in general, but there are corner cases which I couldn't manage to fix yet.
I was wondering if there isn't a better way to do this, other than modifying Qt's source code to store the status information somewhere.
Note: I know that crashes also terminate with a signal, which is SIGABRT
. The main issue here is that a SIGKILL
might tell me that the out of memory killer in Linux was the responsible for the process termination.
Upvotes: 0
Views: 365
Reputation: 91
The solution altering Qt's code under Qt 4, basically involves a simple modification to 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);
The signal will then be available on QProcess::exitCode()
after QProcess::finished()
has been emitted.
Note: Qt5 is using Thiago Macieira's forkfd
, so this solution won't work.
Upvotes: 0
Reputation: 11
This is my code, friend.
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)
{
}
Upvotes: 0