summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoerg Bornemann <joerg.bornemann@qt.io>2016-06-01 09:41:15 +0200
committerJoerg Bornemann <joerg.bornemann@qt.io>2017-03-31 17:37:30 +0000
commit6ba8708a2fdec666172446783a7ff292cd454055 (patch)
tree578c23babbc6da2622efd86d7d2282f26a83c7bf
parent28666d167aa8e602c0bea25ebc4d51b55005db13 (diff)
QProcess::startDetached: support custom process environment
Starting a detached process with a custom process environment can now be achieved by: QProcess p; p.setProgram("foo"); p.setProcessEnvironment(myEnv); p.startDetached(); [ChangeLog][QtCore][QProcess] Added the ability to set a custom process environment for detached processes. Task-number: QTBUG-2284 Change-Id: I49406dffb64fa2aed41ea05cb271bd42eeabb729 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
-rw-r--r--src/corelib/io/qprocess_unix.cpp14
-rw-r--r--src/corelib/io/qprocess_win.cpp11
-rw-r--r--tests/auto/corelib/io/qprocess/testDetached/main.cpp2
-rw-r--r--tests/auto/corelib/io/qprocess/tst_qprocess.cpp26
4 files changed, 42 insertions, 11 deletions
diff --git a/src/corelib/io/qprocess_unix.cpp b/src/corelib/io/qprocess_unix.cpp
index 047a8ddc11..e72773d7a4 100644
--- a/src/corelib/io/qprocess_unix.cpp
+++ b/src/corelib/io/qprocess_unix.cpp
@@ -937,6 +937,14 @@ bool QProcessPrivate::startDetached(qint64 *pid)
argv[i + 1] = ::strdup(QFile::encodeName(arguments.at(i)).constData());
argv[arguments.size() + 1] = 0;
+ // Duplicate the environment.
+ int envc = 0;
+ char **envp = nullptr;
+ if (environment.d.constData()) {
+ QProcessEnvironmentPrivate::MutexLocker locker(environment.d);
+ envp = _q_dupEnvironment(environment.d.constData()->hash, &envc);
+ }
+
QByteArray tmp;
if (!program.contains(QLatin1Char('/'))) {
const QString &exeFilePath = QStandardPaths::findExecutable(program);
@@ -946,7 +954,11 @@ bool QProcessPrivate::startDetached(qint64 *pid)
if (tmp.isEmpty())
tmp = QFile::encodeName(program);
argv[0] = tmp.data();
- qt_safe_execv(argv[0], argv);
+
+ if (envp)
+ qt_safe_execve(argv[0], argv, envp);
+ else
+ qt_safe_execv(argv[0], argv);
struct sigaction noaction;
memset(&noaction, 0, sizeof(noaction));
diff --git a/src/corelib/io/qprocess_win.cpp b/src/corelib/io/qprocess_win.cpp
index 4699936093..6114e3d023 100644
--- a/src/corelib/io/qprocess_win.cpp
+++ b/src/corelib/io/qprocess_win.cpp
@@ -867,6 +867,13 @@ bool QProcessPrivate::startDetached(qint64 *pid)
bool success = false;
PROCESS_INFORMATION pinfo;
+ void *envPtr = nullptr;
+ QByteArray envlist;
+ if (environment.d.constData()) {
+ envlist = qt_create_environment(environment.d.constData()->hash);
+ envPtr = envlist.data();
+ }
+
DWORD dwCreationFlags = (GetConsoleWindow() ? 0 : CREATE_NO_WINDOW);
dwCreationFlags |= CREATE_UNICODE_ENVIRONMENT;
STARTUPINFOW startupInfo = { sizeof( STARTUPINFO ), 0, 0, 0,
@@ -875,7 +882,7 @@ bool QProcessPrivate::startDetached(qint64 *pid)
0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
success = CreateProcess(0, (wchar_t*)args.utf16(),
- 0, 0, FALSE, dwCreationFlags, 0,
+ 0, 0, FALSE, dwCreationFlags, envPtr,
workingDirectory.isEmpty() ? 0 : (wchar_t*)workingDirectory.utf16(),
&startupInfo, &pinfo);
@@ -885,6 +892,8 @@ bool QProcessPrivate::startDetached(qint64 *pid)
if (pid)
*pid = pinfo.dwProcessId;
} else if (GetLastError() == errorElevationRequired) {
+ if (envPtr)
+ qWarning("QProcess: custom environment will be ignored for detached elevated process.");
success = startDetachedUacPrompt(program, arguments, workingDirectory, pid);
}
diff --git a/tests/auto/corelib/io/qprocess/testDetached/main.cpp b/tests/auto/corelib/io/qprocess/testDetached/main.cpp
index 702cabe873..c970ce5aa0 100644
--- a/tests/auto/corelib/io/qprocess/testDetached/main.cpp
+++ b/tests/auto/corelib/io/qprocess/testDetached/main.cpp
@@ -65,6 +65,8 @@ int main(int argc, char **argv)
f.write(QByteArray::number(quint64(GetCurrentProcessId())));
#endif
f.putChar('\n');
+ f.write(qgetenv("tst_QProcess"));
+ f.putChar('\n');
f.close();
diff --git a/tests/auto/corelib/io/qprocess/tst_qprocess.cpp b/tests/auto/corelib/io/qprocess/tst_qprocess.cpp
index 0783a65d8b..5cd1ad5a8b 100644
--- a/tests/auto/corelib/io/qprocess/tst_qprocess.cpp
+++ b/tests/auto/corelib/io/qprocess/tst_qprocess.cpp
@@ -126,7 +126,7 @@ private slots:
void systemEnvironment();
void lockupsInStartDetached();
void waitForReadyReadForNonexistantProcess();
- void detachedWorkingDirectoryAndPid();
+ void detachedProcessParameters();
void startFinishStartFinish();
void invalidProgramString_data();
void invalidProgramString();
@@ -2030,7 +2030,7 @@ void tst_QProcess::fileWriterProcess()
} while (stopWatch.elapsed() < 3000);
}
-void tst_QProcess::detachedWorkingDirectoryAndPid()
+void tst_QProcess::detachedProcessParameters()
{
qint64 pid;
@@ -2042,9 +2042,17 @@ void tst_QProcess::detachedWorkingDirectoryAndPid()
QVERIFY(QFile::exists(workingDir));
- QStringList args;
- args << infoFile.fileName();
- QVERIFY(QProcess::startDetached(QDir::currentPath() + QLatin1String("/testDetached/testDetached"), args, workingDir, &pid));
+ QVERIFY(qgetenv("tst_QProcess").isEmpty());
+ QByteArray envVarValue("foobarbaz");
+ QProcessEnvironment environment = QProcessEnvironment::systemEnvironment();
+ environment.insert(QStringLiteral("tst_QProcess"), QString::fromUtf8(envVarValue));
+
+ QProcess process;
+ process.setProgram(QDir::currentPath() + QLatin1String("/testDetached/testDetached"));
+ process.setArguments(QStringList(infoFile.fileName()));
+ process.setWorkingDirectory(workingDir);
+ process.setProcessEnvironment(environment);
+ QVERIFY(process.startDetached(&pid));
QFileInfo fi(infoFile);
fi.setCaching(false);
@@ -2055,10 +2063,9 @@ void tst_QProcess::detachedWorkingDirectoryAndPid()
}
QVERIFY(infoFile.open(QIODevice::ReadOnly | QIODevice::Text));
- QString actualWorkingDir = QString::fromUtf8(infoFile.readLine());
- actualWorkingDir.chop(1); // strip off newline
- QByteArray processIdString = infoFile.readLine();
- processIdString.chop(1);
+ QString actualWorkingDir = QString::fromUtf8(infoFile.readLine()).trimmed();
+ QByteArray processIdString = infoFile.readLine().trimmed();
+ QByteArray actualEnvVarValue = infoFile.readLine().trimmed();
infoFile.close();
infoFile.remove();
@@ -2068,6 +2075,7 @@ void tst_QProcess::detachedWorkingDirectoryAndPid()
QCOMPARE(actualWorkingDir, workingDir);
QCOMPARE(actualPid, pid);
+ QCOMPARE(actualEnvVarValue, envVarValue);
}
void tst_QProcess::switchReadChannels()