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 start(QIODevice::OpenMode mode);
|
||||||
void startProcess();
|
void startProcess();
|
||||||
#if defined(Q_OS_UNIX)
|
#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
|
#endif
|
||||||
bool processStarted(QString *errorMessage = Q_NULLPTR);
|
bool processStarted(QString *errorMessage = Q_NULLPTR);
|
||||||
void terminateProcess();
|
void terminateProcess();
|
||||||
|
@ -87,6 +87,7 @@ QT_END_NAMESPACE
|
|||||||
|
|
||||||
#include "qprocess.h"
|
#include "qprocess.h"
|
||||||
#include "qprocess_p.h"
|
#include "qprocess_p.h"
|
||||||
|
#include "qstandardpaths.h"
|
||||||
#include "private/qcore_unix_p.h"
|
#include "private/qcore_unix_p.h"
|
||||||
|
|
||||||
#ifdef Q_OS_MAC
|
#ifdef Q_OS_MAC
|
||||||
@ -420,8 +421,16 @@ void QProcessPrivate::startProcess()
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Add the program name to the argument list.
|
// Add the program name to the argument list.
|
||||||
char *dupProgramName = ::strdup(encodedProgramName.constData());
|
argv[0] = nullptr;
|
||||||
argv[0] = dupProgramName;
|
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
|
// Add every argument to the list
|
||||||
for (int i = 0; i < arguments.count(); ++i)
|
for (int i = 0; i < arguments.count(); ++i)
|
||||||
@ -443,29 +452,6 @@ void QProcessPrivate::startProcess()
|
|||||||
workingDirPtr = encodedWorkingDirectory.constData();
|
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.
|
// Start the process manager, and fork off the child process.
|
||||||
pid_t childPid;
|
pid_t childPid;
|
||||||
forkfd = ::forkfd(FFD_CLOEXEC, &childPid);
|
forkfd = ::forkfd(FFD_CLOEXEC, &childPid);
|
||||||
@ -473,16 +459,12 @@ void QProcessPrivate::startProcess()
|
|||||||
if (forkfd != FFD_CHILD_PROCESS) {
|
if (forkfd != FFD_CHILD_PROCESS) {
|
||||||
// Parent process.
|
// Parent process.
|
||||||
// Clean up duplicated memory.
|
// Clean up duplicated memory.
|
||||||
free(dupProgramName);
|
for (int i = 0; i <= arguments.count(); ++i)
|
||||||
for (int i = 1; i <= arguments.count(); ++i)
|
|
||||||
free(argv[i]);
|
free(argv[i]);
|
||||||
for (int i = 0; i < envc; ++i)
|
for (int i = 0; i < envc; ++i)
|
||||||
free(envp[i]);
|
free(envp[i]);
|
||||||
for (int i = 0; i < pathc; ++i)
|
|
||||||
free(path[i]);
|
|
||||||
delete [] argv;
|
delete [] argv;
|
||||||
delete [] envp;
|
delete [] envp;
|
||||||
delete [] path;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// On QNX, if spawnChild failed, childPid will be -1 but forkfd is still 0.
|
// On QNX, if spawnChild failed, childPid will be -1 but forkfd is still 0.
|
||||||
@ -503,7 +485,7 @@ void QProcessPrivate::startProcess()
|
|||||||
|
|
||||||
// Start the child.
|
// Start the child.
|
||||||
if (forkfd == FFD_CHILD_PROCESS) {
|
if (forkfd == FFD_CHILD_PROCESS) {
|
||||||
execChild(workingDirPtr, path, argv, envp);
|
execChild(workingDirPtr, argv, envp);
|
||||||
::_exit(-1);
|
::_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
|
::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]);
|
qt_safe_close(childStartedPipe[0]);
|
||||||
|
|
||||||
// enter the working directory
|
// enter the working directory
|
||||||
@ -582,25 +564,13 @@ void QProcessPrivate::execChild(const char *workingDir, char **path, char **argv
|
|||||||
|
|
||||||
// execute the process
|
// execute the process
|
||||||
if (!envp) {
|
if (!envp) {
|
||||||
qt_safe_execvp(argv[0], argv);
|
qt_safe_execv(argv[0], argv);
|
||||||
callthatfailed = "execvp: ";
|
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]);
|
|
||||||
#endif
|
|
||||||
qt_safe_execve(argv[0], argv, envp);
|
|
||||||
++arg;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
#if defined (QPROCESS_DEBUG)
|
#if defined (QPROCESS_DEBUG)
|
||||||
fprintf(stderr, "QProcessPrivate::execChild() starting %s\n", argv[0]);
|
fprintf(stderr, "QProcessPrivate::execChild() starting %s\n", argv[0]);
|
||||||
#endif
|
#endif
|
||||||
qt_safe_execve(argv[0], argv, envp);
|
qt_safe_execve(argv[0], argv, envp);
|
||||||
}
|
|
||||||
callthatfailed = "execve: ";
|
callthatfailed = "execve: ";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -967,23 +937,16 @@ bool QProcessPrivate::startDetached(qint64 *pid)
|
|||||||
argv[i + 1] = ::strdup(QFile::encodeName(arguments.at(i)).constData());
|
argv[i + 1] = ::strdup(QFile::encodeName(arguments.at(i)).constData());
|
||||||
argv[arguments.size() + 1] = 0;
|
argv[arguments.size() + 1] = 0;
|
||||||
|
|
||||||
|
QByteArray tmp;
|
||||||
if (!program.contains(QLatin1Char('/'))) {
|
if (!program.contains(QLatin1Char('/'))) {
|
||||||
const QString path = QString::fromLocal8Bit(qgetenv("PATH"));
|
const QString &exeFilePath = QStandardPaths::findExecutable(program);
|
||||||
if (!path.isEmpty()) {
|
if (!exeFilePath.isEmpty())
|
||||||
QStringList pathEntries = path.split(QLatin1Char(':'));
|
tmp = QFile::encodeName(exeFilePath);
|
||||||
for (int k = 0; k < pathEntries.size(); ++k) {
|
}
|
||||||
QByteArray tmp = QFile::encodeName(pathEntries.at(k));
|
if (tmp.isEmpty())
|
||||||
if (!tmp.endsWith('/')) tmp += '/';
|
tmp = QFile::encodeName(program);
|
||||||
tmp += QFile::encodeName(program);
|
|
||||||
argv[0] = tmp.data();
|
argv[0] = tmp.data();
|
||||||
qt_safe_execv(argv[0], argv);
|
qt_safe_execv(argv[0], argv);
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
QByteArray tmp = QFile::encodeName(program);
|
|
||||||
argv[0] = tmp.data();
|
|
||||||
qt_safe_execv(argv[0], argv);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct sigaction noaction;
|
struct sigaction noaction;
|
||||||
memset(&noaction, 0, sizeof(noaction));
|
memset(&noaction, 0, sizeof(noaction));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user