summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2014-07-24 12:59:14 -0700
committerThiago Macieira <thiago.macieira@intel.com>2015-01-23 19:13:27 +0100
commit75a2c81b0041df4ca59178cf52d9e5a8815f3524 (patch)
tree3a63d34f62e7872e8ecbbec9233a5eb33886211b
parent1814142b7a11befab315bf3f9d91c4ffbf56ef3e (diff)
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>
-rw-r--r--src/corelib/io/qprocess.cpp18
-rw-r--r--tests/auto/corelib/io/qprocess/tst_qprocess.cpp8
2 files changed, 21 insertions, 5 deletions
diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp
index 976d8503f3..a7d521fc6c 100644
--- a/src/corelib/io/qprocess.cpp
+++ b/src/corelib/io/qprocess.cpp
@@ -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;
}
diff --git a/tests/auto/corelib/io/qprocess/tst_qprocess.cpp b/tests/auto/corelib/io/qprocess/tst_qprocess.cpp
index 3866dd246b..a67d08da6f 100644
--- a/tests/auto/corelib/io/qprocess/tst_qprocess.cpp
+++ b/tests/auto/corelib/io/qprocess/tst_qprocess.cpp
@@ -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));