summaryrefslogtreecommitdiffstats
path: root/src/corelib/io/qprocess.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/io/qprocess.cpp')
-rw-r--r--src/corelib/io/qprocess.cpp145
1 files changed, 116 insertions, 29 deletions
diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp
index ff33607fa1..108ee0b7c3 100644
--- a/src/corelib/io/qprocess.cpp
+++ b/src/corelib/io/qprocess.cpp
@@ -35,6 +35,8 @@ QT_BEGIN_NAMESPACE
\reentrant
\since 4.6
+ \compares equality
+
A process's environment is composed of a set of key=value pairs known as
environment variables. The QProcessEnvironment class wraps that concept
and allows easy manipulation of those variables. It's meant to be used
@@ -184,15 +186,17 @@ QProcessEnvironment &QProcessEnvironment::operator=(const QProcessEnvironment &o
*/
/*!
- \fn bool QProcessEnvironment::operator !=(const QProcessEnvironment &other) const
+ \fn bool QProcessEnvironment::operator!=(const QProcessEnvironment &lhs, const QProcessEnvironment &rhs)
- Returns \c true if this and the \a other QProcessEnvironment objects are different.
+ Returns \c true if the process environment objects \a lhs and \a rhs are different.
\sa operator==()
*/
/*!
- Returns \c true if this and the \a other QProcessEnvironment objects are equal.
+ \fn bool QProcessEnvironment::operator==(const QProcessEnvironment &lhs, const QProcessEnvironment &rhs)
+
+ Returns \c true if the process environment objects \a lhs and \a rhs are equal.
Two QProcessEnvironment objects are considered equal if they have the same
set of key=value pairs. The comparison of keys is done case-sensitive on
@@ -200,12 +204,12 @@ QProcessEnvironment &QProcessEnvironment::operator=(const QProcessEnvironment &o
\sa operator!=(), contains()
*/
-bool QProcessEnvironment::operator==(const QProcessEnvironment &other) const
+bool comparesEqual(const QProcessEnvironment &lhs, const QProcessEnvironment &rhs)
{
- if (d == other.d)
+ if (lhs.d == rhs.d)
return true;
- return d && other.d && d->vars == other.d->vars;
+ return lhs.d && rhs.d && lhs.d->vars == rhs.d->vars;
}
/*!
@@ -816,8 +820,16 @@ void QProcessPrivate::Channel::clear()
Its members are:
\list
\li UnixProcessParameters::flags Flags, see QProcess::UnixProcessFlags
+ \li UnixProcessParameters::lowestFileDescriptorToClose The lowest file
+ descriptor to close.
\endlist
+ When the QProcess::UnixProcessFlags::CloseFileDescriptors flag is set in
+ the \c flags field, QProcess closes the application's open file descriptors
+ before executing the child process. The descriptors 0, 1, and 2 (that is,
+ \c stdin, \c stdout, and \c stderr) are left alone, along with the ones
+ numbered lower than the value of the \c lowestFileDescriptorToClose field.
+
All of the settings above can also be manually achieved by calling the
respective POSIX function from a handler set with
QProcess::setChildProcessModifier(). This structure allows QProcess to deal
@@ -830,15 +842,32 @@ void QProcessPrivate::Channel::clear()
*/
/*!
- \enum QProcess::UnixProcessFlags
+ \enum QProcess::UnixProcessFlag
\since 6.6
These flags can be used in the \c flags field of \l UnixProcessParameters.
- \value CloseNonStandardFileDescriptors Close all file descriptors besides
- \c stdin, \c stdout, and \c stderr, preventing any currently open
- descriptor in the parent process from accidentally leaking to the
- child.
+ \value CloseFileDescriptors Close all file descriptors above the threshold
+ defined by \c lowestFileDescriptorToClose, preventing any currently
+ open descriptor in the parent process from accidentally leaking to the
+ child. The \c stdin, \c stdout, and \c stderr file descriptors are
+ never closed.
+
+ \value [since 6.7] CreateNewSession Starts a new process session, by calling
+ \c{setsid(2)}. This allows the child process to outlive the session
+ the current process is in. This is one of the steps that
+ startDetached() takes to allow the process to detach, and is also one
+ of the steps to daemonize a process.
+
+ \value [since 6.7] DisconnectControllingTerminal Requests that the process
+ disconnect from its controlling terminal, if it has one. If it has
+ none, nothing happens. Processes still connected to a controlling
+ terminal may get a Hang Up (\c SIGHUP) signal if the terminal
+ closes, or one of the other terminal-control signals (\c SIGTSTP, \c
+ SIGTTIN, \c SIGTTOU). Note that on some operating systems, a process
+ may only disconnect from the controlling terminal if it is the
+ session leader, meaning the \c CreateNewSession flag may be
+ required. Like it, this is one of the steps to daemonize a process.
\value IgnoreSigPipe Always sets the \c SIGPIPE signal to ignored
(\c SIG_IGN), even if the \c ResetSignalHandlers flag was set. By
@@ -848,6 +877,12 @@ void QProcessPrivate::Channel::clear()
terminate immediately; with this flag, the write operation fails
without a signal and the child may continue executing.
+ \value [since 6.7] ResetIds Drops any retained, effective user or group
+ ID the current process may still have (see \c{setuid(2)} and
+ \c{setgid(2)}, plus QCoreApplication::setSetuidAllowed()). This is
+ useful if the current process was setuid or setgid and does not wish
+ the child process to retain the elevated privileges.
+
\value ResetSignalHandlers Resets all Unix signal handlers back to their
default state (that is, pass \c SIG_DFL to \c{signal(2)}). This flag
is useful to ensure any ignored (\c SIG_IGN) signal does not affect
@@ -1637,8 +1672,10 @@ std::function<void(void)> QProcess::childProcessModifier() const
\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()}.
+ If the modifier function experiences a failure condition, it can use
+ failChildProcessModifier() to report the situation to the QProcess caller.
+ Alternatively, it may use other methods of stopping the process, like
+ \c{_exit()}, or \c{abort()}.
Certain properties of the child process, such as closing all extraneous
file descriptors or disconnecting from the controlling TTY, can be more
@@ -1665,7 +1702,7 @@ std::function<void(void)> QProcess::childProcessModifier() const
only make use of low-level system calls, such as \c{read()},
\c{write()}, \c{setsid()}, \c{nice()}, and similar.
- \sa childProcessModifier(), setUnixProcessParameters()
+ \sa childProcessModifier(), failChildProcessModifier(), setUnixProcessParameters()
*/
void QProcess::setChildProcessModifier(const std::function<void(void)> &modifier)
{
@@ -1676,6 +1713,46 @@ void QProcess::setChildProcessModifier(const std::function<void(void)> &modifier
}
/*!
+ \fn void QProcess::failChildProcessModifier(const char *description, int error) noexcept
+ \since 6.7
+
+ This functions can be used inside the modifier set with
+ setChildProcessModifier() to indicate an error condition was encountered.
+ When the modifier calls these functions, QProcess will emit errorOccurred()
+ with code QProcess::FailedToStart in the parent process. The \a description
+ can be used to include some information in errorString() to help diagnose
+ the problem, usually the name of the call that failed, similar to the C
+ Library function \c{perror()}. Additionally, the \a error parameter can be
+ an \c{<errno.h>} error code whose text form will also be included.
+
+ For example, a child modifier could prepare an extra file descriptor for
+ the child process this way:
+
+ \code
+ process.setChildProcessModifier([fd, &process]() {
+ if (dup2(fd, TargetFileDescriptor) < 0)
+ process.failChildProcessModifier(errno, "aux comm channel");
+ });
+ process.start();
+ \endcode
+
+ Where \c{fd} is a file descriptor currently open in the parent process. If
+ the \c{dup2()} system call resulted in an \c EBADF condition, the process
+ errorString() could be "Child process modifier reported error: aux comm
+ channel: Bad file descriptor".
+
+ This function does not return to the caller. Using it anywhere except in
+ the child modifier and with the correct QProcess object is undefined
+ behavior.
+
+ \note The implementation imposes a length limit to the \a description
+ parameter to about 500 characters. This does not include the text from the
+ \a error code.
+
+ \sa setChildProcessModifier(), setUnixProcessParameters()
+*/
+
+/*!
\since 6.6
Returns the \l UnixProcessParameters object describing extra flags and
settings that will be applied to the child process on Unix systems. The
@@ -1912,7 +1989,8 @@ QProcessEnvironment QProcess::processEnvironment() const
Returns \c true if the process was started successfully; otherwise
returns \c false (if the operation timed out or if an error
- occurred).
+ occurred). If the process had already started successfully before this
+ function, it returns immediately.
This function can operate without an event loop. It is
useful when writing non-GUI applications and when performing
@@ -1923,9 +2001,6 @@ QProcessEnvironment QProcess::processEnvironment() const
If msecs is -1, this function will not time out.
- \note On some UNIX operating systems, this function may return true but
- the process may later report a QProcess::FailedToStart error.
-
\sa started(), waitForReadyRead(), waitForBytesWritten(), waitForFinished()
*/
bool QProcess::waitForStarted(int msecs)
@@ -2091,18 +2166,22 @@ QByteArray QProcess::readAllStandardError()
/*!
Starts the given \a program in a new process, passing the command line
arguments in \a arguments. See setProgram() for information about how
- QProcess searches for the executable to be run.
+ QProcess searches for the executable to be run. The OpenMode is set to \a
+ mode. No further splitting of the arguments is performed.
The QProcess object will immediately enter the Starting state. If the
process starts successfully, QProcess will emit started(); otherwise,
- errorOccurred() will be emitted.
-
- \note Processes are started asynchronously, which means the started()
- and errorOccurred() signals may be delayed. Call waitForStarted() to make
- sure the process has started (or has failed to start) and those signals
- have been emitted.
-
- \note No further splitting of the arguments is performed.
+ errorOccurred() will be emitted. Do note that on platforms that are able to
+ start child processes synchronously (notably Windows), those signals will
+ be emitted before this function returns and this QProcess object will
+ transition to either QProcess::Running or QProcess::NotRunning state,
+ respectively. On others paltforms, the started() and errorOccurred()
+ signals will be delayed.
+
+ Call waitForStarted() to make sure the process has started (or has failed
+ to start) and those signals have been emitted. It is safe to call that
+ function even if the process starting state is already known, though the
+ signal will not be emitted again.
\b{Windows:} The arguments are quoted and joined into a command line
that is compatible with the \c CommandLineToArgvW() Windows function.
@@ -2111,12 +2190,16 @@ QByteArray QProcess::readAllStandardError()
not follow the \c CommandLineToArgvW() rules is cmd.exe and, by
consequence, all batch scripts.
- The OpenMode is set to \a mode.
-
If the QProcess object is already running a process, a warning may be
printed at the console, and the existing process will continue running
unaffected.
+ \note Success at starting the child process only implies the operating
+ system has successfully created the process and assigned the resources
+ every process has, such as its process ID. The child process may crash or
+ otherwise fail very early and thus not produce its expected output. On most
+ operating systems, this may include dynamic linking errors.
+
\sa processId(), started(), waitForStarted(), setNativeArguments()
*/
void QProcess::start(const QString &program, const QStringList &arguments, OpenMode mode)
@@ -2198,6 +2281,10 @@ void QProcess::start(OpenMode mode)
void QProcess::startCommand(const QString &command, OpenMode mode)
{
QStringList args = splitCommand(command);
+ if (args.isEmpty()) {
+ qWarning("QProcess::startCommand: empty or whitespace-only command was provided");
+ return;
+ }
const QString program = args.takeFirst();
start(program, args, mode);
}