QProcess: make setWorkingDirectory stop launch if the dir doesn't exist

[ChangeLog][QtCore][QProcess] Fixed a bug that caused QProcess to launch
a child process on Unix even if the directory specified with
setWorkingDirectory did not exist.

Task-number: QTBUG-47271
Change-Id: Ib306f8f647014b399b87ffff13f195158b0e52f5
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@theqtcompany.com>
This commit is contained in:
Thiago Macieira 2015-07-16 17:41:15 -07:00
parent ee0fd87007
commit db2fc7843c
2 changed files with 31 additions and 8 deletions

View File

@ -672,9 +672,9 @@ void QProcessPrivate::execChild(const char *workingDir, char **path, char **argv
qt_safe_close(childStartedPipe[0]);
// enter the working directory
if (workingDir) {
if (QT_CHDIR(workingDir) == -1)
qWarning("QProcessPrivate::execChild() failed to chdir to %s", workingDir);
if (workingDir && QT_CHDIR(workingDir) == -1) {
// failed, stop the process
goto report_errno;
}
// this is a virtual call, and it base behavior is to do nothing.
@ -703,6 +703,7 @@ void QProcessPrivate::execChild(const char *workingDir, char **path, char **argv
}
// notify failure
report_errno:
QString error = qt_error_string(errno);
#if defined (QPROCESS_DEBUG)
fprintf(stderr, "QProcessPrivate::execChild() failed (%s), notifying parent process\n", qPrintable(error));

View File

@ -122,9 +122,8 @@ private slots:
void removeFileWhileProcessIsRunning();
void fileWriterProcess();
void switchReadChannels();
#ifdef Q_OS_WIN
void setWorkingDirectory();
#endif // Q_OS_WIN
void setNonExistentWorkingDirectory();
#endif // not Q_OS_WINCE
void exitStatus_data();
@ -2192,15 +2191,19 @@ void tst_QProcess::switchReadChannels()
#endif
//-----------------------------------------------------------------------------
#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
#ifndef Q_OS_WINCE
// Q_OS_WIN - setWorkingDirectory will chdir before starting the process on unices
// Windows CE does not support working directory logic
void tst_QProcess::setWorkingDirectory()
{
process = new QProcess;
process->setWorkingDirectory("test");
process->start("testSetWorkingDirectory/testSetWorkingDirectory");
QVERIFY(process->waitForFinished());
// use absolute path because on Windows, the executable is relative to the parent's CWD
// while on Unix with fork it's relative to the child's (with posix_spawn, it could be either).
process->start(QFileInfo("testSetWorkingDirectory/testSetWorkingDirectory").absoluteFilePath());
QVERIFY2(process->waitForFinished(), process->errorString().toLocal8Bit());
QByteArray workingDir = process->readAllStandardOutput();
QCOMPARE(QDir("test").canonicalPath(), QDir(workingDir.constData()).canonicalPath());
@ -2208,6 +2211,25 @@ void tst_QProcess::setWorkingDirectory()
delete process;
process = 0;
}
//-----------------------------------------------------------------------------
void tst_QProcess::setNonExistentWorkingDirectory()
{
process = new QProcess;
process->setWorkingDirectory("this/directory/should/not/exist/for/sure");
// use absolute path because on Windows, the executable is relative to the parent's CWD
// while on Unix with fork it's relative to the child's (with posix_spawn, it could be either).
process->start(QFileInfo("testSetWorkingDirectory/testSetWorkingDirectory").absoluteFilePath());
QVERIFY(!process->waitForFinished());
#ifdef QPROCESS_USE_SPAWN
QEXPECT_FAIL("", "QProcess cannot detect failure to start when using posix_spawn()", Continue);
#endif
QCOMPARE(int(process->error()), int(QProcess::FailedToStart));
delete process;
process = 0;
}
#endif
//-----------------------------------------------------------------------------