diff options
Diffstat (limited to 'src/corelib/io')
-rw-r--r-- | src/corelib/io/qprocess.cpp | 76 | ||||
-rw-r--r-- | src/corelib/io/qprocess.h | 15 | ||||
-rw-r--r-- | src/corelib/io/qprocess_p.h | 2 | ||||
-rw-r--r-- | src/corelib/io/qprocess_unix.cpp | 7 |
4 files changed, 78 insertions, 22 deletions
diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp index 8e8664fda4..483c99ed5f 100644 --- a/src/corelib/io/qprocess.cpp +++ b/src/corelib/io/qprocess.cpp @@ -1529,7 +1529,7 @@ QProcess::CreateProcessArgumentModifier QProcess::createProcessArgumentsModifier \note This function is available only on the Windows platform and requires C++11. - \sa QProcess::CreateProcessArgumentModifier + \sa QProcess::CreateProcessArgumentModifier, setChildProcessModifier() */ void QProcess::setCreateProcessArgumentsModifier(CreateProcessArgumentModifier modifier) { @@ -1539,6 +1539,59 @@ void QProcess::setCreateProcessArgumentsModifier(CreateProcessArgumentModifier m #endif +#if defined(Q_OS_UNIX) || defined(Q_QDOC) +/*! + \since 6.0 + + Returns the modifier function previously set by calling + setChildProcessModifier(). + + \note This function is only available on Unix platforms. + + \sa setChildProcessModifier() +*/ +std::function<void(void)> QProcess::childProcessModifier() const +{ + Q_D(const QProcess); + return d->childProcessModifier; +} + +/*! + \since 6.0 + + Sets the \a modifier function for the child process, for Unix systems + (including \macos; for Windows, see setCreateProcessArgumentsModifier()). + The function contained by the \a modifier argument will be invoked in the + child process after \c{fork()} is completed and QProcess has set up the + standard file descriptors for the child process, but before \c{execve()}, + inside start(). The modifier is useful to change certain properties of the + child process, such as setting up additional file descriptors or closing + others, changing the nice level, disconnecting from the controlling TTY, + etc. + + The following shows an example of setting up a child process to run without + privileges: + + \snippet code/src_corelib_io_qprocess.cpp 4 + + If the modifier function needs to exit the process, remember to use + \c{_exit()}, not \c{exit()}. + + \note In multithreaded applications, this function must be careful not to + call any functions that may lock mutexes that may have been in use in + other threads (in general, using only functions defined by POSIX as + "async-signal-safe" is advised). Most of the Qt API is unsafe inside this + callback, including qDebug(), and may lead to deadlocks. + + \sa childProcessModifier() +*/ +void QProcess::setChildProcessModifier(const std::function<void(void)> &modifier) +{ + Q_D(QProcess); + d->childProcessModifier = modifier; +} +#endif + /*! If QProcess has been assigned a working directory, this function returns the working directory that the QProcess will enter before the program has @@ -1843,25 +1896,16 @@ void QProcess::setProcessState(ProcessState state) emit stateChanged(state, QPrivateSignal()); } +#if QT_VERSION < QT_VERSION_CHECK(7,0,0) /*! - This function is called in the child process context just before the - program is executed on Unix or \macos (i.e., after \c fork(), but before - \c execve()). Reimplement this function to do last minute initialization - of the child process. Example: - - \snippet code/src_corelib_io_qprocess.cpp 4 - - You cannot exit the process (by calling exit(), for instance) from - this function. If you need to stop the program before it starts - execution, your workaround is to emit finished() and then call - exit(). - - \warning This function is called by QProcess on Unix and \macos - only. On Windows and QNX, it is not called. + \internal */ -void QProcess::setupChildProcess() +auto QProcess::setupChildProcess() -> Use_setChildProcessModifier_Instead { + Q_UNREACHABLE(); + return {}; } +#endif /*! \reimp */ diff --git a/src/corelib/io/qprocess.h b/src/corelib/io/qprocess.h index 9e497c3871..77980e012c 100644 --- a/src/corelib/io/qprocess.h +++ b/src/corelib/io/qprocess.h @@ -205,6 +205,10 @@ public: CreateProcessArgumentModifier createProcessArgumentsModifier() const; void setCreateProcessArgumentsModifier(CreateProcessArgumentModifier modifier); #endif // Q_OS_WIN || Q_CLANG_QDOC +#if defined(Q_OS_UNIX) || defined(Q_CLANG_QDOC) + std::function<void(void)> childProcessModifier() const; + void setChildProcessModifier(const std::function<void(void)> &modifier); +#endif QString workingDirectory() const; void setWorkingDirectory(const QString &dir); @@ -263,8 +267,6 @@ Q_SIGNALS: protected: void setProcessState(ProcessState state); - virtual void setupChildProcess(); - // QIODevice qint64 readData(char *data, qint64 maxlen) override; qint64 writeData(const char *data, qint64 len) override; @@ -273,6 +275,15 @@ private: Q_DECLARE_PRIVATE(QProcess) Q_DISABLE_COPY(QProcess) +#if QT_VERSION < QT_VERSION_CHECK(7,0,0) + // ### Qt7: Remove this struct and the virtual function; they're here only + // to cause build errors in Qt 5 code that wasn't updated to Qt 6's + // setChildProcessModifier() + struct Use_setChildProcessModifier_Instead {}; + QT_DEPRECATED_X("Use setChildProcessModifier() instead") + virtual Use_setChildProcessModifier_Instead setupChildProcess(); +#endif + Q_PRIVATE_SLOT(d_func(), bool _q_canReadStandardOutput()) Q_PRIVATE_SLOT(d_func(), bool _q_canReadStandardError()) Q_PRIVATE_SLOT(d_func(), bool _q_canWrite()) diff --git a/src/corelib/io/qprocess_p.h b/src/corelib/io/qprocess_p.h index 2587530c09..7cb70cc95c 100644 --- a/src/corelib/io/qprocess_p.h +++ b/src/corelib/io/qprocess_p.h @@ -322,6 +322,8 @@ public: #if defined(Q_OS_WIN) QString nativeArguments; QProcess::CreateProcessArgumentModifier modifyCreateProcessArgs; +#else + std::function<void(void)> childProcessModifier; #endif QProcessEnvironment environment; diff --git a/src/corelib/io/qprocess_unix.cpp b/src/corelib/io/qprocess_unix.cpp index 50390e57f5..f14e78f94e 100644 --- a/src/corelib/io/qprocess_unix.cpp +++ b/src/corelib/io/qprocess_unix.cpp @@ -459,7 +459,7 @@ void QProcessPrivate::startProcess() // safe with vfork semantics: suspend the parent execution until the child // either execve()s or _exit()s. int ffdflags = FFD_CLOEXEC; - if (typeid(*q) != typeid(QProcess)) + if (childProcessModifier) ffdflags |= FFD_USE_FORK; pid_t childPid; forkfd = ::forkfd(ffdflags , &childPid); @@ -544,7 +544,6 @@ void QProcessPrivate::execChild(const char *workingDir, char **argv, char **envp { ::signal(SIGPIPE, SIG_DFL); // reset the signal that we ignored - Q_Q(QProcess); ChildError error = { 0, {} }; // force zeroing of function[8] // copy the stdin socket if asked to (without closing on exec) @@ -574,8 +573,8 @@ void QProcessPrivate::execChild(const char *workingDir, char **argv, char **envp goto report_errno; } - // this is a virtual call, and it base behavior is to do nothing. - q->setupChildProcess(); + if (childProcessModifier) + childProcessModifier(); // execute the process if (!envp) { |