1/****************************************************************************
2**
3** Copyright (C) 2021 The Qt Company Ltd.
4** Copyright (C) 2022 Intel Corporation.
5** Contact: https://www.qt.io/licensing/
6**
7** This file is part of the QtCore module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial License Usage
11** Licensees holding valid commercial Qt licenses may use this file in
12** accordance with the commercial license agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and The Qt Company. For licensing terms
15** and conditions see https://www.qt.io/terms-conditions. For further
16** information use the contact form at https://www.qt.io/contact-us.
17**
18** GNU Lesser General Public License Usage
19** Alternatively, this file may be used under the terms of the GNU Lesser
20** General Public License version 3 as published by the Free Software
21** Foundation and appearing in the file LICENSE.LGPL3 included in the
22** packaging of this file. Please review the following information to
23** ensure the GNU Lesser General Public License version 3 requirements
24** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
25**
26** GNU General Public License Usage
27** Alternatively, this file may be used under the terms of the GNU
28** General Public License version 2.0 or (at your option) the GNU General
29** Public license version 3 or any later version approved by the KDE Free
30** Qt Foundation. The licenses are as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
32** included in the packaging of this file. Please review the following
33** information to ensure the GNU General Public License requirements will
34** be met: https://www.gnu.org/licenses/gpl-2.0.html and
35** https://www.gnu.org/licenses/gpl-3.0.html.
36**
37** $QT_END_LICENSE$
38**
39****************************************************************************/
40
41//#define QPROCESS_DEBUG
42#include "qdebug.h"
43
44#if QT_CONFIG(process) && defined(QPROCESS_DEBUG)
45#include "private/qtools_p.h"
46#include <ctype.h>
47
48/*
49 Returns a human readable representation of the first \a len
50 characters in \a data.
51*/
52QT_BEGIN_NAMESPACE
53static QByteArray qt_prettyDebug(const char *data, int len, int maxSize)
54{
55 if (!data) return "(null)";
56 QByteArray out;
57 for (int i = 0; i < len; ++i) {
58 char c = data[i];
59 if (isprint(c)) {
60 out += c;
61 } else switch (c) {
62 case '\n': out += "\\n"; break;
63 case '\r': out += "\\r"; break;
64 case '\t': out += "\\t"; break;
65 default: {
66 const char buf[] = {
67 '\\',
68 QtMiscUtils::toOct(uchar(c) / 64),
69 QtMiscUtils::toOct(uchar(c) % 64 / 8),
70 QtMiscUtils::toOct(uchar(c) % 8),
71 0
72 };
73 out += buf;
74 }
75 }
76 }
77
78 if (len < maxSize)
79 out += "...";
80
81 return out;
82}
83QT_END_NAMESPACE
84#endif
85
86#include "qplatformdefs.h"
87
88#include "qprocess.h"
89#include "qprocess_p.h"
90#include "qstandardpaths.h"
91#include "private/qcore_unix_p.h"
92#include "private/qlocking_p.h"
93
94#ifdef Q_OS_MAC
95#include <private/qcore_mac_p.h>
96#endif
97
98#include <private/qcoreapplication_p.h>
99#include <private/qthread_p.h>
100#include <qfile.h>
101#include <qfileinfo.h>
102#include <qdir.h>
103#include <qlist.h>
104#include <qmutex.h>
105#include <qsocketnotifier.h>
106#include <qthread.h>
107#include <qelapsedtimer.h>
108
109#ifdef Q_OS_QNX
110# include <sys/neutrino.h>
111#endif
112
113#include <errno.h>
114#include <stdlib.h>
115#include <string.h>
116
117#if QT_CONFIG(process)
118#include <forkfd.h>
119#endif
120
121QT_BEGIN_NAMESPACE
122
123#if !defined(Q_OS_DARWIN)
124
125QT_BEGIN_INCLUDE_NAMESPACE
126extern char **environ;
127QT_END_INCLUDE_NAMESPACE
128
129QProcessEnvironment QProcessEnvironment::systemEnvironment()
130{
131 QProcessEnvironment env;
132 const char *entry;
133 for (int count = 0; (entry = environ[count]); ++count) {
134 const char *equal = strchr(s: entry, c: '=');
135 if (!equal)
136 continue;
137
138 QByteArray name(entry, equal - entry);
139 QByteArray value(equal + 1);
140 env.d->vars.insert(akey: QProcessEnvironmentPrivate::Key(name),
141 avalue: QProcessEnvironmentPrivate::Value(value));
142 }
143 return env;
144}
145
146#endif // !defined(Q_OS_DARWIN)
147
148#if QT_CONFIG(process)
149
150namespace {
151struct QProcessPoller
152{
153 QProcessPoller(const QProcessPrivate &proc);
154
155 int poll(int timeout);
156
157 pollfd &stdinPipe() { return pfds[0]; }
158 pollfd &stdoutPipe() { return pfds[1]; }
159 pollfd &stderrPipe() { return pfds[2]; }
160 pollfd &forkfd() { return pfds[3]; }
161 pollfd &childStartedPipe() { return pfds[4]; }
162
163 enum { n_pfds = 5 };
164 pollfd pfds[n_pfds];
165};
166
167QProcessPoller::QProcessPoller(const QProcessPrivate &proc)
168{
169 for (int i = 0; i < n_pfds; i++)
170 pfds[i] = qt_make_pollfd(fd: -1, POLLIN);
171
172 stdoutPipe().fd = proc.stdoutChannel.pipe[0];
173 stderrPipe().fd = proc.stderrChannel.pipe[0];
174
175 if (!proc.writeBuffer.isEmpty()) {
176 stdinPipe().fd = proc.stdinChannel.pipe[1];
177 stdinPipe().events = POLLOUT;
178 }
179
180 forkfd().fd = proc.forkfd;
181
182 if (proc.processState == QProcess::Starting)
183 childStartedPipe().fd = proc.childStartedPipe[0];
184}
185
186int QProcessPoller::poll(int timeout)
187{
188 const nfds_t nfds = (childStartedPipe().fd == -1) ? 4 : 5;
189 return qt_poll_msecs(fds: pfds, nfds, timeout);
190}
191} // anonymous namespace
192
193static bool qt_pollfd_check(const pollfd &pfd, short revents)
194{
195 return pfd.fd >= 0 && (pfd.revents & (revents | POLLHUP | POLLERR | POLLNVAL)) != 0;
196}
197
198static int qt_create_pipe(int *pipe)
199{
200 if (pipe[0] != -1)
201 qt_safe_close(fd: pipe[0]);
202 if (pipe[1] != -1)
203 qt_safe_close(fd: pipe[1]);
204 int pipe_ret = qt_safe_pipe(pipefd: pipe);
205 if (pipe_ret != 0) {
206 qErrnoWarning(msg: "QProcessPrivate::createPipe: Cannot create pipe %p", pipe);
207 }
208 return pipe_ret;
209}
210
211void QProcessPrivate::destroyPipe(int *pipe)
212{
213 if (pipe[1] != -1) {
214 qt_safe_close(fd: pipe[1]);
215 pipe[1] = -1;
216 }
217 if (pipe[0] != -1) {
218 qt_safe_close(fd: pipe[0]);
219 pipe[0] = -1;
220 }
221}
222
223void QProcessPrivate::closeChannel(Channel *channel)
224{
225 destroyPipe(pipe: channel->pipe);
226}
227
228/*
229 Create the pipes to a QProcessPrivate::Channel.
230
231 This function must be called in order: stdin, stdout, stderr
232*/
233bool QProcessPrivate::openChannel(Channel &channel)
234{
235 Q_Q(QProcess);
236
237 if (&channel == &stderrChannel && processChannelMode == QProcess::MergedChannels) {
238 channel.pipe[0] = -1;
239 channel.pipe[1] = -1;
240 return true;
241 }
242
243 if (channel.type == Channel::Normal) {
244 // we're piping this channel to our own process
245 if (qt_create_pipe(pipe: channel.pipe) != 0)
246 return false;
247
248 // create the socket notifiers
249 if (threadData.loadRelaxed()->hasEventDispatcher()) {
250 if (&channel == &stdinChannel) {
251 channel.notifier = new QSocketNotifier(channel.pipe[1],
252 QSocketNotifier::Write, q);
253 channel.notifier->setEnabled(false);
254 QObject::connect(sender: channel.notifier, SIGNAL(activated(QSocketDescriptor)),
255 receiver: q, SLOT(_q_canWrite()));
256 } else {
257 channel.notifier = new QSocketNotifier(channel.pipe[0],
258 QSocketNotifier::Read, q);
259 const char *receiver;
260 if (&channel == &stdoutChannel)
261 receiver = SLOT(_q_canReadStandardOutput());
262 else
263 receiver = SLOT(_q_canReadStandardError());
264 QObject::connect(sender: channel.notifier, SIGNAL(activated(QSocketDescriptor)),
265 receiver: q, member: receiver);
266 }
267 }
268
269 return true;
270 } else if (channel.type == Channel::Redirect) {
271 // we're redirecting the channel to/from a file
272 QByteArray fname = QFile::encodeName(fileName: channel.file);
273
274 if (&channel == &stdinChannel) {
275 // try to open in read-only mode
276 channel.pipe[1] = -1;
277 if ( (channel.pipe[0] = qt_safe_open(pathname: fname, O_RDONLY)) != -1)
278 return true; // success
279 setErrorAndEmit(error: QProcess::FailedToStart,
280 description: QProcess::tr(s: "Could not open input redirection for reading"));
281 } else {
282 int mode = O_WRONLY | O_CREAT;
283 if (channel.append)
284 mode |= O_APPEND;
285 else
286 mode |= O_TRUNC;
287
288 channel.pipe[0] = -1;
289 if ( (channel.pipe[1] = qt_safe_open(pathname: fname, flags: mode, mode: 0666)) != -1)
290 return true; // success
291
292 setErrorAndEmit(error: QProcess::FailedToStart,
293 description: QProcess::tr(s: "Could not open input redirection for reading"));
294 }
295 cleanup();
296 return false;
297 } else {
298 Q_ASSERT_X(channel.process, "QProcess::start", "Internal error");
299
300 Channel *source;
301 Channel *sink;
302
303 if (channel.type == Channel::PipeSource) {
304 // we are the source
305 source = &channel;
306 sink = &channel.process->stdinChannel;
307
308 Q_ASSERT(source == &stdoutChannel);
309 Q_ASSERT(sink->process == this && sink->type == Channel::PipeSink);
310 } else {
311 // we are the sink;
312 source = &channel.process->stdoutChannel;
313 sink = &channel;
314
315 Q_ASSERT(sink == &stdinChannel);
316 Q_ASSERT(source->process == this && source->type == Channel::PipeSource);
317 }
318
319 if (source->pipe[1] != INVALID_Q_PIPE || sink->pipe[0] != INVALID_Q_PIPE) {
320 // already created, do nothing
321 return true;
322 } else {
323 Q_ASSERT(source->pipe[0] == INVALID_Q_PIPE && source->pipe[1] == INVALID_Q_PIPE);
324 Q_ASSERT(sink->pipe[0] == INVALID_Q_PIPE && sink->pipe[1] == INVALID_Q_PIPE);
325
326 Q_PIPE pipe[2] = { -1, -1 };
327 if (qt_create_pipe(pipe) != 0)
328 return false;
329 sink->pipe[0] = pipe[0];
330 source->pipe[1] = pipe[1];
331
332 return true;
333 }
334 }
335}
336
337static char **_q_dupEnvironment(const QProcessEnvironmentPrivate::Map &environment, int *envc)
338{
339 *envc = 0;
340 if (environment.isEmpty())
341 return nullptr;
342
343 char **envp = new char *[environment.count() + 2];
344 envp[environment.count()] = nullptr;
345 envp[environment.count() + 1] = nullptr;
346
347 auto it = environment.constBegin();
348 const auto end = environment.constEnd();
349 for ( ; it != end; ++it) {
350 QByteArray key = it.key();
351 QByteArray value = it.value().bytes();
352 key.reserve(asize: key.length() + 1 + value.length());
353 key.append(c: '=');
354 key.append(a: value);
355
356 envp[(*envc)++] = ::strdup(s: key.constData());
357 }
358
359 return envp;
360}
361
362void QProcessPrivate::startProcess()
363{
364 Q_Q(QProcess);
365
366#if defined (QPROCESS_DEBUG)
367 qDebug("QProcessPrivate::startProcess()");
368#endif
369
370 // Initialize pipes
371 if (!openChannel(channel&: stdinChannel) ||
372 !openChannel(channel&: stdoutChannel) ||
373 !openChannel(channel&: stderrChannel) ||
374 qt_create_pipe(pipe: childStartedPipe) != 0) {
375 setErrorAndEmit(error: QProcess::FailedToStart, description: qt_error_string(errno));
376 cleanup();
377 return;
378 }
379
380 if (threadData.loadRelaxed()->hasEventDispatcher()) {
381 startupSocketNotifier = new QSocketNotifier(childStartedPipe[0],
382 QSocketNotifier::Read, q);
383 QObject::connect(sender: startupSocketNotifier, SIGNAL(activated(QSocketDescriptor)),
384 receiver: q, SLOT(_q_startupNotification()));
385 }
386
387 // Start the process (platform dependent)
388 q->setProcessState(QProcess::Starting);
389
390 // Create argument list with right number of elements, and set the final
391 // one to 0.
392 char **argv = new char *[arguments.count() + 2];
393 argv[arguments.count() + 1] = nullptr;
394
395 // Encode the program name.
396 QByteArray encodedProgramName = QFile::encodeName(fileName: program);
397#ifdef Q_OS_MAC
398 // allow invoking of .app bundles on the Mac.
399 QFileInfo fileInfo(program);
400 if (encodedProgramName.endsWith(".app") && fileInfo.isDir()) {
401 QCFType<CFURLRef> url = CFURLCreateWithFileSystemPath(0,
402 QCFString(fileInfo.absoluteFilePath()),
403 kCFURLPOSIXPathStyle, true);
404 {
405 // CFBundle is not reentrant, since CFBundleCreate might return a reference
406 // to a cached bundle object. Protect the bundle calls with a mutex lock.
407 static QBasicMutex cfbundleMutex;
408 const auto locker = qt_scoped_lock(cfbundleMutex);
409 QCFType<CFBundleRef> bundle = CFBundleCreate(0, url);
410 // 'executableURL' can be either relative or absolute ...
411 QCFType<CFURLRef> executableURL = CFBundleCopyExecutableURL(bundle);
412 // not to depend on caching - make sure it's always absolute.
413 url = CFURLCopyAbsoluteURL(executableURL);
414 }
415 if (url) {
416 const QCFString str = CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle);
417 encodedProgramName += (QDir::separator() + QDir(program).relativeFilePath(QString::fromCFString(str))).toUtf8();
418 }
419 }
420#endif
421
422 // Add the program name to the argument list.
423 argv[0] = nullptr;
424 if (!program.contains(c: QLatin1Char('/'))) {
425 // findExecutable() returns its argument if it's an absolute path,
426 // otherwise it searches $PATH; returns empty if not found (we handle
427 // that case much later)
428 const QString &exeFilePath = QStandardPaths::findExecutable(executableName: program);
429 argv[0] = ::strdup(s: QFile::encodeName(fileName: exeFilePath).constData());
430 } else {
431 argv[0] = ::strdup(s: encodedProgramName.constData());
432 }
433
434 // Add every argument to the list
435 for (int i = 0; i < arguments.count(); ++i)
436 argv[i + 1] = ::strdup(s: QFile::encodeName(fileName: arguments.at(i)).constData());
437
438 // Duplicate the environment.
439 int envc = 0;
440 char **envp = nullptr;
441 if (environment.d.constData()) {
442 envp = _q_dupEnvironment(environment: environment.d.constData()->vars, envc: &envc);
443 }
444
445 // Encode the working directory if it's non-empty, otherwise just pass 0.
446 const char *workingDirPtr = nullptr;
447 QByteArray encodedWorkingDirectory;
448 if (!workingDirectory.isEmpty()) {
449 encodedWorkingDirectory = QFile::encodeName(fileName: workingDirectory);
450 workingDirPtr = encodedWorkingDirectory.constData();
451 }
452
453 // Select FFD_USE_FORK and FFD_VFORK_SEMANTICS based on whether there's
454 // user code running in the child process: if there is, we don't know what
455 // the user will want to do, so we err on the safe side and request an
456 // actual fork() (for example, the user could attempt to do some
457 // synchronization with the parent process). But if there isn't, then our
458 // code in execChild() is just a handful of dup2() and a chdir(), so it's
459 // safe with vfork semantics: suspend the parent execution until the child
460 // either execve()s or _exit()s.
461 int ffdflags = FFD_CLOEXEC;
462 if (typeid(*q) != typeid(QProcess))
463 ffdflags |= FFD_USE_FORK;
464 pid_t childPid;
465 forkfd = ::forkfd(flags: ffdflags , ppid: &childPid);
466 int lastForkErrno = errno;
467 if (forkfd != FFD_CHILD_PROCESS) {
468 // Parent process.
469 // Clean up duplicated memory.
470 for (int i = 0; i <= arguments.count(); ++i)
471 free(ptr: argv[i]);
472 for (int i = 0; i < envc; ++i)
473 free(ptr: envp[i]);
474 delete [] argv;
475 delete [] envp;
476 }
477
478 // On QNX, if spawnChild failed, childPid will be -1 but forkfd is still 0.
479 // This is intentional because we only want to handle failure to fork()
480 // here, which is a rare occurrence. Handling of the failure to start is
481 // done elsewhere.
482 if (forkfd == -1) {
483 // Cleanup, report error and return
484#if defined (QPROCESS_DEBUG)
485 qDebug("fork failed: %ls", qUtf16Printable(qt_error_string(lastForkErrno)));
486#endif
487 q->setProcessState(QProcess::NotRunning);
488 setErrorAndEmit(error: QProcess::FailedToStart,
489 description: QProcess::tr(s: "Resource error (fork failure): %1").arg(a: qt_error_string(errorCode: lastForkErrno)));
490 cleanup();
491 return;
492 }
493
494 // Start the child.
495 if (forkfd == FFD_CHILD_PROCESS) {
496 execChild(workingDirectory: workingDirPtr, argv, envp);
497 ::_exit(status: -1);
498 }
499
500 pid = Q_PID(childPid);
501
502 // parent
503 // close the ends we don't use and make all pipes non-blocking
504 qt_safe_close(fd: childStartedPipe[1]);
505 childStartedPipe[1] = -1;
506
507 if (stdinChannel.pipe[0] != -1) {
508 qt_safe_close(fd: stdinChannel.pipe[0]);
509 stdinChannel.pipe[0] = -1;
510 }
511
512 if (stdinChannel.pipe[1] != -1)
513 ::fcntl(fd: stdinChannel.pipe[1], F_SETFL, ::fcntl(fd: stdinChannel.pipe[1], F_GETFL) | O_NONBLOCK);
514
515 if (stdoutChannel.pipe[1] != -1) {
516 qt_safe_close(fd: stdoutChannel.pipe[1]);
517 stdoutChannel.pipe[1] = -1;
518 }
519
520 if (stdoutChannel.pipe[0] != -1)
521 ::fcntl(fd: stdoutChannel.pipe[0], F_SETFL, ::fcntl(fd: stdoutChannel.pipe[0], F_GETFL) | O_NONBLOCK);
522
523 if (stderrChannel.pipe[1] != -1) {
524 qt_safe_close(fd: stderrChannel.pipe[1]);
525 stderrChannel.pipe[1] = -1;
526 }
527 if (stderrChannel.pipe[0] != -1)
528 ::fcntl(fd: stderrChannel.pipe[0], F_SETFL, ::fcntl(fd: stderrChannel.pipe[0], F_GETFL) | O_NONBLOCK);
529
530 if (threadData.loadRelaxed()->eventDispatcher.loadAcquire()) {
531 deathNotifier = new QSocketNotifier(forkfd, QSocketNotifier::Read, q);
532 QObject::connect(sender: deathNotifier, SIGNAL(activated(QSocketDescriptor)),
533 receiver: q, SLOT(_q_processDied()));
534 }
535}
536
537struct ChildError
538{
539 int code;
540 char function[8];
541};
542
543void QProcessPrivate::execChild(const char *workingDir, char **argv, char **envp)
544{
545 ::signal(SIGPIPE, SIG_DFL); // reset the signal that we ignored
546
547 Q_Q(QProcess);
548 ChildError error = { .code: 0, .function: {} }; // force zeroing of function[8]
549
550 // copy the stdin socket if asked to (without closing on exec)
551 if (inputChannelMode != QProcess::ForwardedInputChannel)
552 qt_safe_dup2(oldfd: stdinChannel.pipe[0], STDIN_FILENO, flags: 0);
553
554 // copy the stdout and stderr if asked to
555 if (processChannelMode != QProcess::ForwardedChannels) {
556 if (processChannelMode != QProcess::ForwardedOutputChannel)
557 qt_safe_dup2(oldfd: stdoutChannel.pipe[1], STDOUT_FILENO, flags: 0);
558
559 // merge stdout and stderr if asked to
560 if (processChannelMode == QProcess::MergedChannels) {
561 qt_safe_dup2(STDOUT_FILENO, STDERR_FILENO, flags: 0);
562 } else if (processChannelMode != QProcess::ForwardedErrorChannel) {
563 qt_safe_dup2(oldfd: stderrChannel.pipe[1], STDERR_FILENO, flags: 0);
564 }
565 }
566
567 // make sure this fd is closed if execv() succeeds
568 qt_safe_close(fd: childStartedPipe[0]);
569
570 // enter the working directory
571 if (workingDir && QT_CHDIR(path: workingDir) == -1) {
572 // failed, stop the process
573 strcpy(dest: error.function, src: "chdir");
574 goto report_errno;
575 }
576
577 // this is a virtual call, and it base behavior is to do nothing.
578 q->setupChildProcess();
579
580 // execute the process
581 if (!envp) {
582 qt_safe_execv(path: argv[0], argv);
583 strcpy(dest: error.function, src: "execvp");
584 } else {
585#if defined (QPROCESS_DEBUG)
586 fprintf(stderr, "QProcessPrivate::execChild() starting %s\n", argv[0]);
587#endif
588 qt_safe_execve(filename: argv[0], argv, envp);
589 strcpy(dest: error.function, src: "execve");
590 }
591
592 // notify failure
593 // don't use strerror or any other routines that may allocate memory, since
594 // some buggy libc versions can deadlock on locked mutexes.
595report_errno:
596 error.code = errno;
597 qt_safe_write(fd: childStartedPipe[1], data: &error, len: sizeof(error));
598 childStartedPipe[1] = -1;
599}
600
601bool QProcessPrivate::processStarted(QString *errorMessage)
602{
603 ChildError buf;
604 int ret = qt_safe_read(fd: childStartedPipe[0], data: &buf, maxlen: sizeof(buf));
605
606 if (startupSocketNotifier) {
607 startupSocketNotifier->setEnabled(false);
608 startupSocketNotifier->deleteLater();
609 startupSocketNotifier = nullptr;
610 }
611 qt_safe_close(fd: childStartedPipe[0]);
612 childStartedPipe[0] = -1;
613
614#if defined (QPROCESS_DEBUG)
615 qDebug("QProcessPrivate::processStarted() == %s", i <= 0 ? "true" : "false");
616#endif
617
618 // did we read an error message?
619 if (ret > 0 && errorMessage)
620 *errorMessage = QLatin1String(buf.function) + QLatin1String(": ") + qt_error_string(errorCode: buf.code);
621
622 return ret <= 0;
623}
624
625qint64 QProcessPrivate::bytesAvailableInChannel(const Channel *channel) const
626{
627 Q_ASSERT(channel->pipe[0] != INVALID_Q_PIPE);
628 int nbytes = 0;
629 qint64 available = 0;
630 if (::ioctl(fd: channel->pipe[0], FIONREAD, (char *) &nbytes) >= 0)
631 available = (qint64) nbytes;
632#if defined (QPROCESS_DEBUG)
633 qDebug("QProcessPrivate::bytesAvailableInChannel(%d) == %lld", int(channel - &stdinChannel), available);
634#endif
635 return available;
636}
637
638qint64 QProcessPrivate::readFromChannel(const Channel *channel, char *data, qint64 maxlen)
639{
640 Q_ASSERT(channel->pipe[0] != INVALID_Q_PIPE);
641 qint64 bytesRead = qt_safe_read(fd: channel->pipe[0], data, maxlen);
642#if defined QPROCESS_DEBUG
643 int save_errno = errno;
644 qDebug("QProcessPrivate::readFromChannel(%d, %p \"%s\", %lld) == %lld",
645 int(channel - &stdinChannel),
646 data, qt_prettyDebug(data, bytesRead, 16).constData(), maxlen, bytesRead);
647 errno = save_errno;
648#endif
649 if (bytesRead == -1 && errno == EWOULDBLOCK)
650 return -2;
651 return bytesRead;
652}
653
654bool QProcessPrivate::writeToStdin()
655{
656 const char *data = writeBuffer.readPointer();
657 const qint64 bytesToWrite = writeBuffer.nextDataBlockSize();
658
659 qint64 written = qt_safe_write_nosignal(fd: stdinChannel.pipe[1], data, len: bytesToWrite);
660#if defined QPROCESS_DEBUG
661 qDebug("QProcessPrivate::writeToStdin(), write(%p \"%s\", %lld) == %lld",
662 data, qt_prettyDebug(data, bytesToWrite, 16).constData(), bytesToWrite, written);
663 if (written == -1)
664 qDebug("QProcessPrivate::writeToStdin(), failed to write (%ls)", qUtf16Printable(qt_error_string(errno)));
665#endif
666 if (written == -1) {
667 // If the O_NONBLOCK flag is set and If some data can be written without blocking
668 // the process, write() will transfer what it can and return the number of bytes written.
669 // Otherwise, it will return -1 and set errno to EAGAIN
670 if (errno == EAGAIN)
671 return true;
672
673 closeChannel(channel: &stdinChannel);
674 setErrorAndEmit(error: QProcess::WriteError);
675 return false;
676 }
677 writeBuffer.free(bytes: written);
678 if (!emittedBytesWritten && written != 0) {
679 emittedBytesWritten = true;
680 emit q_func()->bytesWritten(bytes: written);
681 emittedBytesWritten = false;
682 }
683 return true;
684}
685
686void QProcessPrivate::terminateProcess()
687{
688#if defined (QPROCESS_DEBUG)
689 qDebug("QProcessPrivate::terminateProcess()");
690#endif
691 if (pid)
692 ::kill(pid: pid_t(pid), SIGTERM);
693}
694
695void QProcessPrivate::killProcess()
696{
697#if defined (QPROCESS_DEBUG)
698 qDebug("QProcessPrivate::killProcess()");
699#endif
700 if (pid)
701 ::kill(pid: pid_t(pid), SIGKILL);
702}
703
704bool QProcessPrivate::waitForStarted(int msecs)
705{
706#if defined (QPROCESS_DEBUG)
707 qDebug("QProcessPrivate::waitForStarted(%d) waiting for child to start (fd = %d)", msecs,
708 childStartedPipe[0]);
709#endif
710
711 pollfd pfd = qt_make_pollfd(fd: childStartedPipe[0], POLLIN);
712
713 if (qt_poll_msecs(fds: &pfd, nfds: 1, timeout: msecs) == 0) {
714 setError(error: QProcess::Timedout);
715#if defined (QPROCESS_DEBUG)
716 qDebug("QProcessPrivate::waitForStarted(%d) == false (timed out)", msecs);
717#endif
718 return false;
719 }
720
721 bool startedEmitted = _q_startupNotification();
722#if defined (QPROCESS_DEBUG)
723 qDebug("QProcessPrivate::waitForStarted() == %s", startedEmitted ? "true" : "false");
724#endif
725 return startedEmitted;
726}
727
728bool QProcessPrivate::waitForReadyRead(int msecs)
729{
730#if defined (QPROCESS_DEBUG)
731 qDebug("QProcessPrivate::waitForReadyRead(%d)", msecs);
732#endif
733
734 QElapsedTimer stopWatch;
735 stopWatch.start();
736
737 forever {
738 QProcessPoller poller(*this);
739
740 int timeout = qt_subtract_from_timeout(timeout: msecs, elapsed: stopWatch.elapsed());
741 int ret = poller.poll(timeout);
742
743 if (ret < 0) {
744 break;
745 }
746 if (ret == 0) {
747 setError(error: QProcess::Timedout);
748 return false;
749 }
750
751 if (qt_pollfd_check(pfd: poller.childStartedPipe(), POLLIN)) {
752 if (!_q_startupNotification())
753 return false;
754 }
755
756 bool readyReadEmitted = false;
757 if (qt_pollfd_check(pfd: poller.stdoutPipe(), POLLIN)) {
758 bool canRead = _q_canReadStandardOutput();
759 if (currentReadChannel == QProcess::StandardOutput && canRead)
760 readyReadEmitted = true;
761 }
762 if (qt_pollfd_check(pfd: poller.stderrPipe(), POLLIN)) {
763 bool canRead = _q_canReadStandardError();
764 if (currentReadChannel == QProcess::StandardError && canRead)
765 readyReadEmitted = true;
766 }
767 if (readyReadEmitted)
768 return true;
769
770 if (qt_pollfd_check(pfd: poller.stdinPipe(), POLLOUT))
771 _q_canWrite();
772
773 // Signals triggered by I/O may have stopped this process:
774 if (processState == QProcess::NotRunning)
775 return false;
776
777 if (qt_pollfd_check(pfd: poller.forkfd(), POLLIN)) {
778 if (_q_processDied())
779 return false;
780 }
781 }
782 return false;
783}
784
785bool QProcessPrivate::waitForBytesWritten(int msecs)
786{
787#if defined (QPROCESS_DEBUG)
788 qDebug("QProcessPrivate::waitForBytesWritten(%d)", msecs);
789#endif
790
791 QElapsedTimer stopWatch;
792 stopWatch.start();
793
794 while (!writeBuffer.isEmpty()) {
795 QProcessPoller poller(*this);
796
797 int timeout = qt_subtract_from_timeout(timeout: msecs, elapsed: stopWatch.elapsed());
798 int ret = poller.poll(timeout);
799
800 if (ret < 0) {
801 break;
802 }
803
804 if (ret == 0) {
805 setError(error: QProcess::Timedout);
806 return false;
807 }
808
809 if (qt_pollfd_check(pfd: poller.childStartedPipe(), POLLIN)) {
810 if (!_q_startupNotification())
811 return false;
812 }
813
814 if (qt_pollfd_check(pfd: poller.stdinPipe(), POLLOUT))
815 return _q_canWrite();
816
817 if (qt_pollfd_check(pfd: poller.stdoutPipe(), POLLIN))
818 _q_canReadStandardOutput();
819
820 if (qt_pollfd_check(pfd: poller.stderrPipe(), POLLIN))
821 _q_canReadStandardError();
822
823 // Signals triggered by I/O may have stopped this process:
824 if (processState == QProcess::NotRunning)
825 return false;
826
827 if (qt_pollfd_check(pfd: poller.forkfd(), POLLIN)) {
828 if (_q_processDied())
829 return false;
830 }
831 }
832
833 return false;
834}
835
836bool QProcessPrivate::waitForFinished(int msecs)
837{
838#if defined (QPROCESS_DEBUG)
839 qDebug("QProcessPrivate::waitForFinished(%d)", msecs);
840#endif
841
842 QElapsedTimer stopWatch;
843 stopWatch.start();
844
845 forever {
846 QProcessPoller poller(*this);
847
848 int timeout = qt_subtract_from_timeout(timeout: msecs, elapsed: stopWatch.elapsed());
849 int ret = poller.poll(timeout);
850
851 if (ret < 0) {
852 break;
853 }
854 if (ret == 0) {
855 setError(error: QProcess::Timedout);
856 return false;
857 }
858
859 if (qt_pollfd_check(pfd: poller.childStartedPipe(), POLLIN)) {
860 if (!_q_startupNotification())
861 return false;
862 }
863 if (qt_pollfd_check(pfd: poller.stdinPipe(), POLLOUT))
864 _q_canWrite();
865
866 if (qt_pollfd_check(pfd: poller.stdoutPipe(), POLLIN))
867 _q_canReadStandardOutput();
868
869 if (qt_pollfd_check(pfd: poller.stderrPipe(), POLLIN))
870 _q_canReadStandardError();
871
872 // Signals triggered by I/O may have stopped this process:
873 if (processState == QProcess::NotRunning)
874 return true;
875
876 if (qt_pollfd_check(pfd: poller.forkfd(), POLLIN)) {
877 if (_q_processDied())
878 return true;
879 }
880 }
881 return false;
882}
883
884void QProcessPrivate::findExitCode()
885{
886}
887
888bool QProcessPrivate::waitForDeadChild()
889{
890 if (forkfd == -1)
891 return true; // child has already exited
892
893 // read the process information from our fd
894 forkfd_info info;
895 int ret;
896 EINTR_LOOP(ret, forkfd_wait(forkfd, &info, nullptr));
897
898 exitCode = info.status;
899 crashed = info.code != CLD_EXITED;
900
901 delete deathNotifier;
902 deathNotifier = nullptr;
903
904 EINTR_LOOP(ret, forkfd_close(forkfd));
905 forkfd = -1; // Child is dead, don't try to kill it anymore
906
907#if defined QPROCESS_DEBUG
908 qDebug() << "QProcessPrivate::waitForDeadChild() dead with exitCode"
909 << exitCode << ", crashed?" << crashed;
910#endif
911 return true;
912}
913
914bool QProcessPrivate::startDetached(qint64 *pid)
915{
916 QByteArray encodedWorkingDirectory = QFile::encodeName(fileName: workingDirectory);
917
918 // To catch the startup of the child
919 int startedPipe[2];
920 if (qt_safe_pipe(pipefd: startedPipe) != 0)
921 return false;
922 // To communicate the pid of the child
923 int pidPipe[2];
924 if (qt_safe_pipe(pipefd: pidPipe) != 0) {
925 qt_safe_close(fd: startedPipe[0]);
926 qt_safe_close(fd: startedPipe[1]);
927 return false;
928 }
929
930 if ((stdinChannel.type == Channel::Redirect && !openChannel(channel&: stdinChannel))
931 || (stdoutChannel.type == Channel::Redirect && !openChannel(channel&: stdoutChannel))
932 || (stderrChannel.type == Channel::Redirect && !openChannel(channel&: stderrChannel))) {
933 closeChannel(channel: &stdinChannel);
934 closeChannel(channel: &stdoutChannel);
935 closeChannel(channel: &stderrChannel);
936 qt_safe_close(fd: pidPipe[0]);
937 qt_safe_close(fd: pidPipe[1]);
938 qt_safe_close(fd: startedPipe[0]);
939 qt_safe_close(fd: startedPipe[1]);
940 return false;
941 }
942
943 pid_t childPid = fork();
944 if (childPid == 0) {
945 struct sigaction noaction;
946 memset(s: &noaction, c: 0, n: sizeof(noaction));
947 noaction.sa_handler = SIG_IGN;
948 ::sigaction(SIGPIPE, act: &noaction, oact: nullptr);
949
950 ::setsid();
951
952 qt_safe_close(fd: startedPipe[0]);
953 qt_safe_close(fd: pidPipe[0]);
954
955 pid_t doubleForkPid = fork();
956 if (doubleForkPid == 0) {
957 qt_safe_close(fd: pidPipe[1]);
958
959 // copy the stdin socket if asked to (without closing on exec)
960 if (stdinChannel.type == Channel::Redirect)
961 qt_safe_dup2(oldfd: stdinChannel.pipe[0], STDIN_FILENO, flags: 0);
962
963 // copy the stdout and stderr if asked to
964 if (stdoutChannel.type == Channel::Redirect)
965 qt_safe_dup2(oldfd: stdoutChannel.pipe[1], STDOUT_FILENO, flags: 0);
966 if (stderrChannel.type == Channel::Redirect)
967 qt_safe_dup2(oldfd: stderrChannel.pipe[1], STDERR_FILENO, flags: 0);
968
969 if (!encodedWorkingDirectory.isEmpty()) {
970 if (QT_CHDIR(path: encodedWorkingDirectory.constData()) == -1)
971 qWarning(msg: "QProcessPrivate::startDetached: failed to chdir to %s", encodedWorkingDirectory.constData());
972 }
973
974 char **argv = new char *[arguments.size() + 2];
975 for (int i = 0; i < arguments.size(); ++i)
976 argv[i + 1] = ::strdup(s: QFile::encodeName(fileName: arguments.at(i)).constData());
977 argv[arguments.size() + 1] = nullptr;
978
979 // Duplicate the environment.
980 int envc = 0;
981 char **envp = nullptr;
982 if (environment.d.constData()) {
983 envp = _q_dupEnvironment(environment: environment.d.constData()->vars, envc: &envc);
984 }
985
986 QByteArray tmp;
987 if (!program.contains(c: QLatin1Char('/'))) {
988 // findExecutable() returns its argument if it's an absolute path,
989 // otherwise it searches $PATH; returns empty if not found (we handle
990 // that case much later)
991 const QString &exeFilePath = QStandardPaths::findExecutable(executableName: program);
992 tmp = QFile::encodeName(fileName: exeFilePath);
993 } else {
994 tmp = QFile::encodeName(fileName: program);
995 }
996 argv[0] = tmp.data();
997
998 if (envp)
999 qt_safe_execve(filename: argv[0], argv, envp);
1000 else
1001 qt_safe_execv(path: argv[0], argv);
1002
1003 struct sigaction noaction;
1004 memset(s: &noaction, c: 0, n: sizeof(noaction));
1005 noaction.sa_handler = SIG_IGN;
1006 ::sigaction(SIGPIPE, act: &noaction, oact: nullptr);
1007
1008 // '\1' means execv failed
1009 char c = '\1';
1010 qt_safe_write(fd: startedPipe[1], data: &c, len: 1);
1011 qt_safe_close(fd: startedPipe[1]);
1012 ::_exit(status: 1);
1013 } else if (doubleForkPid == -1) {
1014 struct sigaction noaction;
1015 memset(s: &noaction, c: 0, n: sizeof(noaction));
1016 noaction.sa_handler = SIG_IGN;
1017 ::sigaction(SIGPIPE, act: &noaction, oact: nullptr);
1018
1019 // '\2' means internal error
1020 char c = '\2';
1021 qt_safe_write(fd: startedPipe[1], data: &c, len: 1);
1022 }
1023
1024 qt_safe_close(fd: startedPipe[1]);
1025 qt_safe_write(fd: pidPipe[1], data: (const char *)&doubleForkPid, len: sizeof(pid_t));
1026 if (QT_CHDIR(path: "/") == -1)
1027 qWarning(msg: "QProcessPrivate::startDetached: failed to chdir to /");
1028 ::_exit(status: 1);
1029 }
1030
1031 closeChannel(channel: &stdinChannel);
1032 closeChannel(channel: &stdoutChannel);
1033 closeChannel(channel: &stderrChannel);
1034 qt_safe_close(fd: startedPipe[1]);
1035 qt_safe_close(fd: pidPipe[1]);
1036
1037 if (childPid == -1) {
1038 qt_safe_close(fd: startedPipe[0]);
1039 qt_safe_close(fd: pidPipe[0]);
1040 return false;
1041 }
1042
1043 char reply = '\0';
1044 int startResult = qt_safe_read(fd: startedPipe[0], data: &reply, maxlen: 1);
1045 int result;
1046 qt_safe_close(fd: startedPipe[0]);
1047 qt_safe_waitpid(pid: childPid, status: &result, options: 0);
1048 bool success = (startResult != -1 && reply == '\0');
1049 if (success && pid) {
1050 pid_t actualPid = 0;
1051 if (qt_safe_read(fd: pidPipe[0], data: (char *)&actualPid, maxlen: sizeof(pid_t)) == sizeof(pid_t)) {
1052 *pid = actualPid;
1053 } else {
1054 *pid = 0;
1055 }
1056 }
1057 qt_safe_close(fd: pidPipe[0]);
1058 return success;
1059}
1060
1061#endif // QT_CONFIG(process)
1062
1063QT_END_NAMESPACE
1064

source code of qtbase/src/corelib/io/qprocess_unix.cpp