Handle posix_spawn using exit code 127 to indicate fail-to-start

Most posix_spawn implementations are done using fork(), so the only way
to report errors afer fork() is via a special exit code.

Reference: http://pubs.opengroup.org/onlinepubs/009695399/functions/posix_spawn.html
Change-Id: I3a37f81b0cb278bb31e5cb83c87e6b4c034dbc19
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Thiago Macieira 2014-07-24 12:59:14 -07:00
parent 1814142b7a
commit 75a2c81b00
2 changed files with 21 additions and 5 deletions

View File

@ -1078,6 +1078,17 @@ bool QProcessPrivate::_q_processDied()
processError = QProcess::Crashed;
q->setErrorString(QProcess::tr("Process crashed"));
emit q->error(processError);
} else {
#ifdef QPROCESS_USE_SPAWN
// if we're using posix_spawn, waitForStarted always succeeds.
// POSIX documents that the sub-process launched by posix_spawn will exit with code
// 127 if anything prevents the target program from starting.
// http://pubs.opengroup.org/onlinepubs/009695399/functions/posix_spawn.html
if (exitStatus == QProcess::NormalExit && exitCode == 127) {
processError = QProcess::FailedToStart;
q->setErrorString(QProcess::tr("Process failed to start (spawned process exited with code 127)"));
}
#endif
}
bool wasRunning = (processState == QProcess::Running);
@ -1753,6 +1764,9 @@ QProcessEnvironment QProcess::processEnvironment() const
If msecs is -1, this function will not time out.
\note On some UNIX operating systems, this function may return true but
the process may later report a QProcess::FailedToStart error.
\sa started(), waitForReadyRead(), waitForBytesWritten(), waitForFinished()
*/
bool QProcess::waitForStarted(int msecs)
@ -2347,7 +2361,7 @@ int QProcess::execute(const QString &program, const QStringList &arguments)
QProcess process;
process.setReadChannelMode(ForwardedChannels);
process.start(program, arguments);
if (!process.waitForFinished(-1))
if (!process.waitForFinished(-1) || process.error() == FailedToStart)
return -2;
return process.exitStatus() == QProcess::NormalExit ? process.exitCode() : -1;
}
@ -2370,7 +2384,7 @@ int QProcess::execute(const QString &command)
QProcess process;
process.setReadChannelMode(ForwardedChannels);
process.start(command);
if (!process.waitForFinished(-1))
if (!process.waitForFinished(-1) || process.error() == FailedToStart)
return -2;
return process.exitStatus() == QProcess::NormalExit ? process.exitCode() : -1;
}

View File

@ -317,9 +317,6 @@ void tst_QProcess::execute()
{
QCOMPARE(QProcess::execute("testProcessNormal/testProcessNormal",
QStringList() << "arg1" << "arg2"), 0);
#ifdef QPROCESS_USE_SPAWN
QEXPECT_FAIL("", "QProcess cannot detect failure to start when using posix_spawn()", Continue);
#endif
QCOMPARE(QProcess::execute("nonexistingexe"), -2);
}
@ -1527,6 +1524,11 @@ void tst_QProcess::nativeArguments()
void tst_QProcess::exitCodeTest()
{
for (int i = 0; i < 255; ++i) {
#ifdef QPROCESS_USE_SPAWN
// POSIX reserves exit code 127 when using posix_spawn
if (i == 127)
continue;
#endif
QProcess process;
process.start("testExitCodes/testExitCodes " + QString::number(i));
QVERIFY(process.waitForFinished(5000));