diff options
Diffstat (limited to 'src/corelib/io/qprocess.cpp')
-rw-r--r-- | src/corelib/io/qprocess.cpp | 145 |
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); } |