summaryrefslogtreecommitdiffstats
path: root/src/corelib/io
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/io')
-rw-r--r--src/corelib/io/qprocess.cpp76
-rw-r--r--src/corelib/io/qprocess.h15
-rw-r--r--src/corelib/io/qprocess_p.h2
-rw-r--r--src/corelib/io/qprocess_unix.cpp7
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) {