From 31e782cc9609c2f1c201453841f36ed7dae25890 Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Mon, 30 May 2016 17:22:05 +0200 Subject: [PATCH] Add non-static QProcess::startDetached The three static QProcess::startDetached overloads support a limited number of features: program, arguments and working directory. To support more features of QProcess (without adding a plethora of overloads) we add a non-static method startDetached that can be used as follows: QProcess p; p.setProgram("cat"); p.setArguments("meow"); p.setWorkingDirectory("/tmp"); if (!p.startDetached()) qWarning("Cannot start process."); We plan to add support for nativeArguments, processEnvironment, standard{Output|Error}File and maybe more in subsequent commits. [ChangeLog][QtCore][QProcess] Added non-static QProcess::startDetached to support more features for detached processes. Task-number: QTBUG-2058 Task-number: QTBUG-2284 Task-number: QTBUG-37656 Task-number: QTBUG-52405 Task-number: QTBUG-57687 Change-Id: If6fdd57ecb28cd13aa5fff566216a4177f81d339 Reviewed-by: Thiago Macieira Reviewed-by: Rafael Roquetto --- src/corelib/io/qprocess.cpp | 71 +++++++++++++++++++++++++------- src/corelib/io/qprocess.h | 1 + src/corelib/io/qprocess_p.h | 3 +- src/corelib/io/qprocess_unix.cpp | 2 +- src/corelib/io/qprocess_win.cpp | 6 +-- 5 files changed, 62 insertions(+), 21 deletions(-) diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp index c0ec35ff32..a3343423db 100644 --- a/src/corelib/io/qprocess.cpp +++ b/src/corelib/io/qprocess.cpp @@ -2111,6 +2111,46 @@ void QProcess::start(OpenMode mode) d->start(mode); } +/*! + \since 5.10 + + Starts the program set by setProgram() with arguments set by setArguments() + in a new process, and detaches from it. Returns \c true on success; + otherwise returns \c false. If the calling process exits, the + detached process will continue to run unaffected. + + \b{Unix:} The started process will run in its own session and act + like a daemon. + + The process will be started in the directory set by setWorkingDirectory(). + If workingDirectory() is empty, the working directory is inherited + from the calling process. + + \note On QNX, this may cause all application threads to + temporarily freeze. + + If the function is successful then *\a pid is set to the process + identifier of the started process. + + \sa start() + \sa startDetached(const QString &program, const QStringList &arguments, + const QString &workingDirectory, qint64 *pid) + \sa startDetached(const QString &command) +*/ +bool QProcess::startDetached(qint64 *pid) +{ + Q_D(QProcess); + if (d->processState != NotRunning) { + qWarning("QProcess::startDetached: Process is already running"); + return false; + } + if (d->program.isEmpty()) { + d->setErrorAndEmit(QProcess::FailedToStart, tr("No program defined")); + return false; + } + return d->startDetached(pid); +} + /*! Starts the program set by setProgram() with arguments set by setArguments(). The OpenMode is set to \a mode. @@ -2445,6 +2485,8 @@ int QProcess::execute(const QString &command) } /*! + \overload startDetached() + Starts the program \a program with the arguments \a arguments in a new process, and detaches from it. Returns \c true on success; otherwise returns \c false. If the calling process exits, the @@ -2452,16 +2494,10 @@ int QProcess::execute(const QString &command) Argument handling is identical to the respective start() overload. - \b{Unix:} The started process will run in its own session and act - like a daemon. - The process will be started in the directory \a workingDirectory. If \a workingDirectory is empty, the working directory is inherited from the calling process. - \note On QNX, this may cause all application threads to - temporarily freeze. - If the function is successful then *\a pid is set to the process identifier of the started process. @@ -2472,10 +2508,11 @@ bool QProcess::startDetached(const QString &program, const QString &workingDirectory, qint64 *pid) { - return QProcessPrivate::startDetached(program, - arguments, - workingDirectory, - pid); + QProcess process; + process.setProgram(program); + process.setArguments(arguments); + process.setWorkingDirectory(workingDirectory); + return process.startDetached(pid); } /*! @@ -2484,11 +2521,14 @@ bool QProcess::startDetached(const QString &program, bool QProcess::startDetached(const QString &program, const QStringList &arguments) { - return QProcessPrivate::startDetached(program, arguments); + QProcess process; + process.setProgram(program); + process.setArguments(arguments); + return process.startDetached(); } /*! - \overload + \overload startDetached() Starts the command \a command in a new process, and detaches from it. Returns \c true on success; otherwise returns \c false. @@ -2506,9 +2546,10 @@ bool QProcess::startDetached(const QString &command) if (args.isEmpty()) return false; - const QString prog = args.takeFirst(); - - return QProcessPrivate::startDetached(prog, args); + QProcess process; + process.setProgram(args.takeFirst()); + process.setArguments(args); + return process.startDetached(); } QT_BEGIN_INCLUDE_NAMESPACE diff --git a/src/corelib/io/qprocess.h b/src/corelib/io/qprocess.h index 19157bdd02..c8aef2f0b1 100644 --- a/src/corelib/io/qprocess.h +++ b/src/corelib/io/qprocess.h @@ -163,6 +163,7 @@ public: void start(const QString &command, OpenMode mode = ReadWrite); #endif void start(OpenMode mode = ReadWrite); + bool startDetached(qint64 *pid = nullptr); bool open(OpenMode mode = ReadWrite) Q_DECL_OVERRIDE; QString program() const; diff --git a/src/corelib/io/qprocess_p.h b/src/corelib/io/qprocess_p.h index 6e0630eb66..9c4a2d8e1b 100644 --- a/src/corelib/io/qprocess_p.h +++ b/src/corelib/io/qprocess_p.h @@ -368,8 +368,7 @@ public: qint64 pipeWriterBytesToWrite() const; #endif - static bool startDetached(const QString &program, const QStringList &arguments, const QString &workingDirectory = QString(), - qint64 *pid = 0); + bool startDetached(qint64 *pPid); int exitCode; QProcess::ExitStatus exitStatus; diff --git a/src/corelib/io/qprocess_unix.cpp b/src/corelib/io/qprocess_unix.cpp index 795229419c..dcbdebd4aa 100644 --- a/src/corelib/io/qprocess_unix.cpp +++ b/src/corelib/io/qprocess_unix.cpp @@ -925,7 +925,7 @@ bool QProcessPrivate::waitForDeadChild() return true; } -bool QProcessPrivate::startDetached(const QString &program, const QStringList &arguments, const QString &workingDirectory, qint64 *pid) +bool QProcessPrivate::startDetached(qint64 *pid) { QByteArray encodedWorkingDirectory = QFile::encodeName(workingDirectory); diff --git a/src/corelib/io/qprocess_win.cpp b/src/corelib/io/qprocess_win.cpp index 329d1842f0..4699936093 100644 --- a/src/corelib/io/qprocess_win.cpp +++ b/src/corelib/io/qprocess_win.cpp @@ -859,7 +859,7 @@ static bool startDetachedUacPrompt(const QString &programIn, const QStringList & return true; } -bool QProcessPrivate::startDetached(const QString &program, const QStringList &arguments, const QString &workingDir, qint64 *pid) +bool QProcessPrivate::startDetached(qint64 *pid) { static const DWORD errorElevationRequired = 740; @@ -876,7 +876,7 @@ bool QProcessPrivate::startDetached(const QString &program, const QStringList &a }; success = CreateProcess(0, (wchar_t*)args.utf16(), 0, 0, FALSE, dwCreationFlags, 0, - workingDir.isEmpty() ? 0 : (wchar_t*)workingDir.utf16(), + workingDirectory.isEmpty() ? 0 : (wchar_t*)workingDirectory.utf16(), &startupInfo, &pinfo); if (success) { @@ -885,7 +885,7 @@ bool QProcessPrivate::startDetached(const QString &program, const QStringList &a if (pid) *pid = pinfo.dwProcessId; } else if (GetLastError() == errorElevationRequired) { - success = startDetachedUacPrompt(program, arguments, workingDir, pid); + success = startDetachedUacPrompt(program, arguments, workingDirectory, pid); } return success;