Simplify Unix implementation of QProcess::start{Process|Detached}
Use QStandardPaths::findExecutable instead of duplicated implementations. Change-Id: Ia944f1d343d8c215fc2b6e78dae6b2bfffbba688 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
parent
31e782cc96
commit
28666d167a
@ -353,7 +353,7 @@ public:
|
||||
void start(QIODevice::OpenMode mode);
|
||||
void startProcess();
|
||||
#if defined(Q_OS_UNIX)
|
||||
void execChild(const char *workingDirectory, char **path, char **argv, char **envp);
|
||||
void execChild(const char *workingDirectory, char **argv, char **envp);
|
||||
#endif
|
||||
bool processStarted(QString *errorMessage = Q_NULLPTR);
|
||||
void terminateProcess();
|
||||
|
@ -87,6 +87,7 @@ QT_END_NAMESPACE
|
||||
|
||||
#include "qprocess.h"
|
||||
#include "qprocess_p.h"
|
||||
#include "qstandardpaths.h"
|
||||
#include "private/qcore_unix_p.h"
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
@ -420,8 +421,16 @@ void QProcessPrivate::startProcess()
|
||||
#endif
|
||||
|
||||
// Add the program name to the argument list.
|
||||
char *dupProgramName = ::strdup(encodedProgramName.constData());
|
||||
argv[0] = dupProgramName;
|
||||
argv[0] = nullptr;
|
||||
if (!program.contains(QLatin1Char('/'))) {
|
||||
const QString &exeFilePath = QStandardPaths::findExecutable(program);
|
||||
if (!exeFilePath.isEmpty()) {
|
||||
const QByteArray &tmp = QFile::encodeName(exeFilePath);
|
||||
argv[0] = ::strdup(tmp.constData());
|
||||
}
|
||||
}
|
||||
if (!argv[0])
|
||||
argv[0] = ::strdup(encodedProgramName.constData());
|
||||
|
||||
// Add every argument to the list
|
||||
for (int i = 0; i < arguments.count(); ++i)
|
||||
@ -443,29 +452,6 @@ void QProcessPrivate::startProcess()
|
||||
workingDirPtr = encodedWorkingDirectory.constData();
|
||||
}
|
||||
|
||||
// If the program does not specify a path, generate a list of possible
|
||||
// locations for the binary using the PATH environment variable.
|
||||
char **path = 0;
|
||||
int pathc = 0;
|
||||
if (!program.contains(QLatin1Char('/'))) {
|
||||
const QString pathEnv = QString::fromLocal8Bit(qgetenv("PATH"));
|
||||
if (!pathEnv.isEmpty()) {
|
||||
QStringList pathEntries = pathEnv.split(QLatin1Char(':'), QString::SkipEmptyParts);
|
||||
if (!pathEntries.isEmpty()) {
|
||||
pathc = pathEntries.size();
|
||||
path = new char *[pathc + 1];
|
||||
path[pathc] = 0;
|
||||
|
||||
for (int k = 0; k < pathEntries.size(); ++k) {
|
||||
QByteArray tmp = QFile::encodeName(pathEntries.at(k));
|
||||
if (!tmp.endsWith('/')) tmp += '/';
|
||||
tmp += encodedProgramName;
|
||||
path[k] = ::strdup(tmp.constData());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Start the process manager, and fork off the child process.
|
||||
pid_t childPid;
|
||||
forkfd = ::forkfd(FFD_CLOEXEC, &childPid);
|
||||
@ -473,16 +459,12 @@ void QProcessPrivate::startProcess()
|
||||
if (forkfd != FFD_CHILD_PROCESS) {
|
||||
// Parent process.
|
||||
// Clean up duplicated memory.
|
||||
free(dupProgramName);
|
||||
for (int i = 1; i <= arguments.count(); ++i)
|
||||
for (int i = 0; i <= arguments.count(); ++i)
|
||||
free(argv[i]);
|
||||
for (int i = 0; i < envc; ++i)
|
||||
free(envp[i]);
|
||||
for (int i = 0; i < pathc; ++i)
|
||||
free(path[i]);
|
||||
delete [] argv;
|
||||
delete [] envp;
|
||||
delete [] path;
|
||||
}
|
||||
|
||||
// On QNX, if spawnChild failed, childPid will be -1 but forkfd is still 0.
|
||||
@ -503,7 +485,7 @@ void QProcessPrivate::startProcess()
|
||||
|
||||
// Start the child.
|
||||
if (forkfd == FFD_CHILD_PROCESS) {
|
||||
execChild(workingDirPtr, path, argv, envp);
|
||||
execChild(workingDirPtr, argv, envp);
|
||||
::_exit(-1);
|
||||
}
|
||||
|
||||
@ -544,7 +526,7 @@ void QProcessPrivate::startProcess()
|
||||
}
|
||||
}
|
||||
|
||||
void QProcessPrivate::execChild(const char *workingDir, char **path, char **argv, char **envp)
|
||||
void QProcessPrivate::execChild(const char *workingDir, char **argv, char **envp)
|
||||
{
|
||||
::signal(SIGPIPE, SIG_DFL); // reset the signal that we ignored
|
||||
|
||||
@ -567,7 +549,7 @@ void QProcessPrivate::execChild(const char *workingDir, char **path, char **argv
|
||||
}
|
||||
}
|
||||
|
||||
// make sure this fd is closed if execvp() succeeds
|
||||
// make sure this fd is closed if execv() succeeds
|
||||
qt_safe_close(childStartedPipe[0]);
|
||||
|
||||
// enter the working directory
|
||||
@ -582,25 +564,13 @@ void QProcessPrivate::execChild(const char *workingDir, char **path, char **argv
|
||||
|
||||
// execute the process
|
||||
if (!envp) {
|
||||
qt_safe_execvp(argv[0], argv);
|
||||
callthatfailed = "execvp: ";
|
||||
qt_safe_execv(argv[0], argv);
|
||||
callthatfailed = "execv: ";
|
||||
} else {
|
||||
if (path) {
|
||||
char **arg = path;
|
||||
while (*arg) {
|
||||
argv[0] = *arg;
|
||||
#if defined (QPROCESS_DEBUG)
|
||||
fprintf(stderr, "QProcessPrivate::execChild() searching / starting %s\n", argv[0]);
|
||||
fprintf(stderr, "QProcessPrivate::execChild() starting %s\n", argv[0]);
|
||||
#endif
|
||||
qt_safe_execve(argv[0], argv, envp);
|
||||
++arg;
|
||||
}
|
||||
} else {
|
||||
#if defined (QPROCESS_DEBUG)
|
||||
fprintf(stderr, "QProcessPrivate::execChild() starting %s\n", argv[0]);
|
||||
#endif
|
||||
qt_safe_execve(argv[0], argv, envp);
|
||||
}
|
||||
qt_safe_execve(argv[0], argv, envp);
|
||||
callthatfailed = "execve: ";
|
||||
}
|
||||
|
||||
@ -967,23 +937,16 @@ bool QProcessPrivate::startDetached(qint64 *pid)
|
||||
argv[i + 1] = ::strdup(QFile::encodeName(arguments.at(i)).constData());
|
||||
argv[arguments.size() + 1] = 0;
|
||||
|
||||
QByteArray tmp;
|
||||
if (!program.contains(QLatin1Char('/'))) {
|
||||
const QString path = QString::fromLocal8Bit(qgetenv("PATH"));
|
||||
if (!path.isEmpty()) {
|
||||
QStringList pathEntries = path.split(QLatin1Char(':'));
|
||||
for (int k = 0; k < pathEntries.size(); ++k) {
|
||||
QByteArray tmp = QFile::encodeName(pathEntries.at(k));
|
||||
if (!tmp.endsWith('/')) tmp += '/';
|
||||
tmp += QFile::encodeName(program);
|
||||
argv[0] = tmp.data();
|
||||
qt_safe_execv(argv[0], argv);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
QByteArray tmp = QFile::encodeName(program);
|
||||
argv[0] = tmp.data();
|
||||
qt_safe_execv(argv[0], argv);
|
||||
const QString &exeFilePath = QStandardPaths::findExecutable(program);
|
||||
if (!exeFilePath.isEmpty())
|
||||
tmp = QFile::encodeName(exeFilePath);
|
||||
}
|
||||
if (tmp.isEmpty())
|
||||
tmp = QFile::encodeName(program);
|
||||
argv[0] = tmp.data();
|
||||
qt_safe_execv(argv[0], argv);
|
||||
|
||||
struct sigaction noaction;
|
||||
memset(&noaction, 0, sizeof(noaction));
|
||||
|
Loading…
x
Reference in New Issue
Block a user