QProcess::startDetached/Unix: simplify handling of the pipes
Use a structure that will automatically close them for us. This doesn't apply to startProcess() because the pipes there are long-lived (though each of them in QProcessPrivate could be an AutoPipe...). The destructor only runs in the parent process, so the child processes don't need to worry about setting file descriptors to -1. Pick-to: 6.1 Change-Id: Ic90d8429a0eb4837971dfffd1664ed98f3d74d1c Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@gmx.de>
This commit is contained in:
parent
089bcb0074
commit
f0ce50d335
@ -148,6 +148,26 @@ QProcessEnvironment QProcessEnvironment::systemEnvironment()
|
||||
#if QT_CONFIG(process)
|
||||
|
||||
namespace {
|
||||
struct AutoPipe
|
||||
{
|
||||
int pipe[2] = { -1, -1 };
|
||||
AutoPipe(int flags = 0)
|
||||
{
|
||||
qt_safe_pipe(pipe, flags);
|
||||
}
|
||||
~AutoPipe()
|
||||
{
|
||||
for (int fd : pipe) {
|
||||
if (fd >= 0)
|
||||
qt_safe_close(fd);
|
||||
}
|
||||
}
|
||||
|
||||
explicit operator bool() const { return pipe[0] >= 0; }
|
||||
int &operator[](int idx) { return pipe[idx]; }
|
||||
int operator[](int idx) const { return pipe[idx]; }
|
||||
};
|
||||
|
||||
struct QProcessPoller
|
||||
{
|
||||
QProcessPoller(const QProcessPrivate &proc);
|
||||
@ -882,30 +902,18 @@ bool QProcessPrivate::startDetached(qint64 *pid)
|
||||
{
|
||||
QByteArray encodedWorkingDirectory = QFile::encodeName(workingDirectory);
|
||||
|
||||
// To catch the startup of the child
|
||||
int startedPipe[2];
|
||||
if (qt_safe_pipe(startedPipe) != 0) {
|
||||
// To catch the startup of the child and communicate its pid
|
||||
AutoPipe startedPipe, pidPipe;
|
||||
if (!startedPipe || !pidPipe) {
|
||||
setErrorAndEmit(QProcess::FailedToStart, QLatin1String("pipe: ") + qt_error_string(errno));
|
||||
return false;
|
||||
}
|
||||
// To communicate the pid of the child
|
||||
int pidPipe[2];
|
||||
if (qt_safe_pipe(pidPipe) != 0) {
|
||||
setErrorAndEmit(QProcess::FailedToStart, QLatin1String("pipe: ") + qt_error_string(errno));
|
||||
qt_safe_close(startedPipe[0]);
|
||||
qt_safe_close(startedPipe[1]);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!openChannelsForDetached()) {
|
||||
// openChannel sets the error string
|
||||
closeChannel(&stdinChannel);
|
||||
closeChannel(&stdoutChannel);
|
||||
closeChannel(&stderrChannel);
|
||||
qt_safe_close(pidPipe[0]);
|
||||
qt_safe_close(pidPipe[1]);
|
||||
qt_safe_close(startedPipe[0]);
|
||||
qt_safe_close(startedPipe[1]);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -976,20 +984,18 @@ bool QProcessPrivate::startDetached(qint64 *pid)
|
||||
closeChannel(&stdinChannel);
|
||||
closeChannel(&stdoutChannel);
|
||||
closeChannel(&stderrChannel);
|
||||
qt_safe_close(startedPipe[1]);
|
||||
qt_safe_close(pidPipe[1]);
|
||||
|
||||
if (childPid == -1) {
|
||||
qt_safe_close(startedPipe[0]);
|
||||
qt_safe_close(pidPipe[0]);
|
||||
setErrorAndEmit(QProcess::FailedToStart, QLatin1String("fork: ") + qt_error_string(savedErrno));
|
||||
return false;
|
||||
}
|
||||
|
||||
qt_safe_close(startedPipe[1]);
|
||||
startedPipe[1] = -1;
|
||||
|
||||
char reply = '\0';
|
||||
int startResult = qt_safe_read(startedPipe[0], &reply, 1);
|
||||
int result;
|
||||
qt_safe_close(startedPipe[0]);
|
||||
qt_safe_waitpid(childPid, &result, 0);
|
||||
|
||||
bool success = (startResult != -1 && reply == '\0');
|
||||
@ -1003,7 +1009,6 @@ bool QProcessPrivate::startDetached(qint64 *pid)
|
||||
*pid = -1;
|
||||
setErrorAndEmit(QProcess::FailedToStart);
|
||||
}
|
||||
qt_safe_close(pidPipe[0]);
|
||||
return success;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user