Qt 4.8
qprocess_unix.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtCore module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 //#define QPROCESS_DEBUG
43 #include "qdebug.h"
44 
45 #ifndef QT_NO_PROCESS
46 
47 #if defined QPROCESS_DEBUG
48 #include "qstring.h"
49 #include <ctype.h>
50 
51 /*
52  Returns a human readable representation of the first \a len
53  characters in \a data.
54 */
56 static QByteArray qt_prettyDebug(const char *data, int len, int maxSize)
57 {
58  if (!data) return "(null)";
59  QByteArray out;
60  for (int i = 0; i < len; ++i) {
61  char c = data[i];
62  if (isprint(c)) {
63  out += c;
64  } else switch (c) {
65  case '\n': out += "\\n"; break;
66  case '\r': out += "\\r"; break;
67  case '\t': out += "\\t"; break;
68  default:
69  QString tmp;
70  tmp.sprintf("\\%o", c);
71  out += tmp.toLatin1();
72  }
73  }
74 
75  if (len < maxSize)
76  out += "...";
77 
78  return out;
79 }
81 #endif
82 
83 #include "qplatformdefs.h"
84 
85 #include "qprocess.h"
86 #include "qprocess_p.h"
87 #include "private/qcore_unix_p.h"
88 
89 #ifdef Q_OS_MAC
90 #include <private/qcore_mac_p.h>
91 #endif
92 
93 #include <private/qcoreapplication_p.h>
94 #include <private/qthread_p.h>
95 #include <qfile.h>
96 #include <qfileinfo.h>
97 #include <qlist.h>
98 #include <qhash.h>
99 #include <qmutex.h>
100 #include <qsemaphore.h>
101 #include <qsocketnotifier.h>
102 #include <qthread.h>
103 #include <qelapsedtimer.h>
104 
105 #include <errno.h>
106 #include <stdlib.h>
107 #include <string.h>
108 #ifdef Q_OS_QNX
109 #include "qvarlengtharray.h"
110 
111 #include <spawn.h>
112 #include <sys/neutrino.h>
113 #endif
114 
115 
117 
118 // POSIX requires PIPE_BUF to be 512 or larger
119 // so we will use 512
120 static const int errorBufferMax = 512;
121 
122 #ifdef Q_OS_INTEGRITY
123 static inline char *strdup(const char *data)
124 {
125  return qstrdup(data);
126 }
127 #endif
128 
131 static void qt_sa_sigchld_sigaction(int signum, siginfo_t *info, void *context)
132 {
133  // *Never* use the info or contect variables in this function
134  // (except for passing them to the next signal in the chain).
135  // We cannot be sure if another library or if the application
136  // installed a signal handler for SIGCHLD without SA_SIGINFO
137  // and fails to pass the arguments to us. If they do that,
138  // these arguments contain garbage and we'd most likely crash.
139 
140  qt_safe_write(qt_qprocess_deadChild_pipe[1], "", 1);
141 #if defined (QPROCESS_DEBUG)
142  fprintf(stderr, "*** SIGCHLD\n");
143 #endif
144 
145  // load as volatile
146  volatile struct sigaction *vsa = &qt_sa_old_sigchld_handler;
147 
148  if (qt_sa_old_sigchld_handler.sa_flags & SA_SIGINFO) {
149  void (*oldAction)(int, siginfo_t *, void *) = vsa->sa_sigaction;
150 
151  if (oldAction)
152  oldAction(signum, info, context);
153  } else {
154  void (*oldAction)(int) = vsa->sa_handler;
155 
156  if (oldAction && oldAction != SIG_IGN)
157  oldAction(signum);
158  }
159 }
160 
161 static inline void add_fd(int &nfds, int fd, fd_set *fdset)
162 {
163  FD_SET(fd, fdset);
164  if ((fd) > nfds)
165  nfds = fd;
166 }
167 
168 struct QProcessInfo {
172  pid_t pid;
174 };
175 
176 class QProcessManager : public QThread
177 {
178  Q_OBJECT
179 public:
180  QProcessManager();
181  ~QProcessManager();
182 
183  void run();
184  void catchDeadChildren();
185  void add(pid_t pid, QProcess *process);
186  void remove(QProcess *process);
187  void lock();
188  void unlock();
189 
190 private:
193 };
194 
195 
196 Q_GLOBAL_STATIC(QMutex, processManagerGlobalMutex)
197 
199  // The constructor of QProcessManager should be called only once
200  // so we cannot use Q_GLOBAL_STATIC directly for QProcessManager
201  QMutex *mutex = processManagerGlobalMutex();
202  QMutexLocker locker(mutex);
204  return &processManager;
205 }
206 
208 {
209 #if defined (QPROCESS_DEBUG)
210  qDebug() << "QProcessManager::QProcessManager()";
211 #endif
212  // initialize the dead child pipe and make it non-blocking. in the
213  // extremely unlikely event that the pipe fills up, we do not under any
214  // circumstances want to block.
215  qt_safe_pipe(qt_qprocess_deadChild_pipe, O_NONBLOCK);
216 
217  // set up the SIGCHLD handler, which writes a single byte to the dead
218  // child pipe every time a child dies.
219 
220  struct sigaction action;
221  // use the old handler as template, i.e., preserve the signal mask
222  // otherwise the original signal handler might be interrupted although it
223  // was marked to never be interrupted
224  ::sigaction(SIGCHLD, NULL, &action);
225  action.sa_sigaction = qt_sa_sigchld_sigaction;
226  // set the SA_SIGINFO flag such that we can use the three argument handler
227  // function
228  action.sa_flags = SA_NOCLDSTOP | SA_SIGINFO;
229  ::sigaction(SIGCHLD, &action, &qt_sa_old_sigchld_handler);
230 }
231 
233 {
234  // notify the thread that we're shutting down.
235  qt_safe_write(qt_qprocess_deadChild_pipe[1], "@", 1);
236  qt_safe_close(qt_qprocess_deadChild_pipe[1]);
237  wait();
238 
239  // on certain unixes, closing the reading end of the pipe will cause
240  // select in run() to block forever, rather than return with EBADF.
241  qt_safe_close(qt_qprocess_deadChild_pipe[0]);
242 
243  qt_qprocess_deadChild_pipe[0] = -1;
244  qt_qprocess_deadChild_pipe[1] = -1;
245 
246  qDeleteAll(children.values());
247  children.clear();
248 
249  struct sigaction currentAction;
250  ::sigaction(SIGCHLD, 0, &currentAction);
251  if (currentAction.sa_sigaction == qt_sa_sigchld_sigaction) {
253  }
254 }
255 
257 {
258  forever {
259  fd_set readset;
260  FD_ZERO(&readset);
261  FD_SET(qt_qprocess_deadChild_pipe[0], &readset);
262 
263 #if defined (QPROCESS_DEBUG)
264  qDebug() << "QProcessManager::run() waiting for children to die";
265 #endif
266 
267  // block forever, or until activity is detected on the dead child
268  // pipe. the only other peers are the SIGCHLD signal handler, and the
269  // QProcessManager destructor.
270  int nselect = select(qt_qprocess_deadChild_pipe[0] + 1, &readset, 0, 0, 0);
271  if (nselect < 0) {
272  if (errno == EINTR)
273  continue;
274  break;
275  }
276 
277  // empty only one byte from the pipe, even though several SIGCHLD
278  // signals may have been delivered in the meantime, to avoid race
279  // conditions.
280  char c;
281  if (qt_safe_read(qt_qprocess_deadChild_pipe[0], &c, 1) < 0 || c == '@')
282  break;
283 
284  // catch any and all children that we can.
285  catchDeadChildren();
286  }
287 }
288 
290 {
291  QMutexLocker locker(&mutex);
292 
293  // try to catch all children whose pid we have registered, and whose
294  // deathPipe is still valid (i.e, we have not already notified it).
295  QHash<int, QProcessInfo *>::Iterator it = children.begin();
296  while (it != children.end()) {
297  // notify all children that they may have died. they need to run
298  // waitpid() in their own thread.
299  QProcessInfo *info = it.value();
300  qt_safe_write(info->deathPipe, "", 1);
301 
302 #if defined (QPROCESS_DEBUG)
303  qDebug() << "QProcessManager::run() sending death notice to" << info->process;
304 #endif
305  ++it;
306  }
307 }
308 
310 
312 {
313 #if defined (QPROCESS_DEBUG)
314  qDebug() << "QProcessManager::add() adding pid" << pid << "process" << process;
315 #endif
316 
317  // insert a new info structure for this process
319  info->process = process;
320  info->deathPipe = process->d_func()->deathPipe[1];
321  info->exitResult = 0;
322  info->pid = pid;
323 
324  int serial = idCounter.fetchAndAddRelaxed(1);
325  process->d_func()->serial = serial;
326  children.insert(serial, info);
327 }
328 
330 {
331  QMutexLocker locker(&mutex);
332 
333  int serial = process->d_func()->serial;
334  QProcessInfo *info = children.take(serial);
335 #if defined (QPROCESS_DEBUG)
336  if (info)
337  qDebug() << "QProcessManager::remove() removing pid" << info->pid << "process" << info->process;
338 #endif
339  delete info;
340 }
341 
343 {
344  mutex.lock();
345 }
346 
348 {
349  mutex.unlock();
350 }
351 
352 static int qt_create_pipe(int *pipe)
353 {
354  if (pipe[0] != -1)
355  qt_safe_close(pipe[0]);
356  if (pipe[1] != -1)
357  qt_safe_close(pipe[1]);
358  int pipe_ret = qt_safe_pipe(pipe);
359  if (pipe_ret != 0) {
360  qWarning("QProcessPrivate::createPipe: Cannot create pipe %p: %s",
362  }
363  return pipe_ret;
364 }
365 
367 {
368  if (pipe[1] != -1) {
369  qt_safe_close(pipe[1]);
370  pipe[1] = -1;
371  }
372  if (pipe[0] != -1) {
373  qt_safe_close(pipe[0]);
374  pipe[0] = -1;
375  }
376 }
377 
378 /*
379  Create the pipes to a QProcessPrivate::Channel.
380 
381  This function must be called in order: stdin, stdout, stderr
382 */
384 {
385  Q_Q(QProcess);
386 
387  if (&channel == &stderrChannel && processChannelMode == QProcess::MergedChannels) {
388  channel.pipe[0] = -1;
389  channel.pipe[1] = -1;
390  return true;
391  }
392 
393  if (channel.type == Channel::Normal) {
394  // we're piping this channel to our own process
395  if (qt_create_pipe(channel.pipe) != 0)
396  return false;
397 
398  // create the socket notifiers
399  if (threadData->eventDispatcher) {
400  if (&channel == &stdinChannel) {
401  channel.notifier = new QSocketNotifier(channel.pipe[1],
403  channel.notifier->setEnabled(false);
404  QObject::connect(channel.notifier, SIGNAL(activated(int)),
405  q, SLOT(_q_canWrite()));
406  } else {
407  channel.notifier = new QSocketNotifier(channel.pipe[0],
409  const char *receiver;
410  if (&channel == &stdoutChannel)
411  receiver = SLOT(_q_canReadStandardOutput());
412  else
413  receiver = SLOT(_q_canReadStandardError());
414  QObject::connect(channel.notifier, SIGNAL(activated(int)),
415  q, receiver);
416  }
417  }
418 
419  return true;
420  } else if (channel.type == Channel::Redirect) {
421  // we're redirecting the channel to/from a file
422  QByteArray fname = QFile::encodeName(channel.file);
423 
424  if (&channel == &stdinChannel) {
425  // try to open in read-only mode
426  channel.pipe[1] = -1;
427  if ( (channel.pipe[0] = qt_safe_open(fname, O_RDONLY)) != -1)
428  return true; // success
429 
430  q->setErrorString(QProcess::tr("Could not open input redirection for reading"));
431  } else {
432  int mode = O_WRONLY | O_CREAT;
433  if (channel.append)
434  mode |= O_APPEND;
435  else
436  mode |= O_TRUNC;
437 
438  channel.pipe[0] = -1;
439  if ( (channel.pipe[1] = qt_safe_open(fname, mode, 0666)) != -1)
440  return true; // success
441 
442  q->setErrorString(QProcess::tr("Could not open output redirection for writing"));
443  }
444 
445  // could not open file
446  processError = QProcess::FailedToStart;
447  emit q->error(processError);
448  cleanup();
449  return false;
450  } else {
451  Q_ASSERT_X(channel.process, "QProcess::start", "Internal error");
452 
453  Channel *source;
454  Channel *sink;
455 
456  if (channel.type == Channel::PipeSource) {
457  // we are the source
458  source = &channel;
459  sink = &channel.process->stdinChannel;
460 
461  Q_ASSERT(source == &stdoutChannel);
462  Q_ASSERT(sink->process == this && sink->type == Channel::PipeSink);
463  } else {
464  // we are the sink;
465  source = &channel.process->stdoutChannel;
466  sink = &channel;
467 
468  Q_ASSERT(sink == &stdinChannel);
469  Q_ASSERT(source->process == this && source->type == Channel::PipeSource);
470  }
471 
472  if (source->pipe[1] != INVALID_Q_PIPE || sink->pipe[0] != INVALID_Q_PIPE) {
473  // already created, do nothing
474  return true;
475  } else {
476  Q_ASSERT(source->pipe[0] == INVALID_Q_PIPE && source->pipe[1] == INVALID_Q_PIPE);
477  Q_ASSERT(sink->pipe[0] == INVALID_Q_PIPE && sink->pipe[1] == INVALID_Q_PIPE);
478 
479  Q_PIPE pipe[2] = { -1, -1 };
480  if (qt_create_pipe(pipe) != 0)
481  return false;
482  sink->pipe[0] = pipe[0];
483  source->pipe[1] = pipe[1];
484 
485  return true;
486  }
487  }
488 }
489 
491 #if defined(Q_OS_MAC) && !defined(Q_OS_IOS)
492 # include <crt_externs.h>
493 # define environ (*_NSGetEnviron())
494 #else
495  extern char **environ;
496 #endif
498 
500 {
502 #if !defined(Q_OS_IOS)
503  const char *entry;
504  for (int count = 0; (entry = environ[count]); ++count) {
505  const char *equal = strchr(entry, '=');
506  if (!equal)
507  continue;
508 
509  QByteArray name(entry, equal - entry);
510  QByteArray value(equal + 1);
513  }
514 #endif
515  return env;
516 }
517 
518 static char **_q_dupEnvironment(const QProcessEnvironmentPrivate::Hash &environment, int *envc)
519 {
520  *envc = 0;
521  if (environment.isEmpty())
522  return 0;
523 
524  // if LD_LIBRARY_PATH exists in the current environment, but
525  // not in the environment list passed by the programmer, then
526  // copy it over.
527 #if defined(Q_OS_MAC)
528  static const char libraryPath[] = "DYLD_LIBRARY_PATH";
529 #else
530  static const char libraryPath[] = "LD_LIBRARY_PATH";
531 #endif
532  const QByteArray envLibraryPath = qgetenv(libraryPath);
533  bool needToAddLibraryPath = !envLibraryPath.isEmpty() &&
534  !environment.contains(QProcessEnvironmentPrivate::Key(QByteArray(libraryPath)));
535 
536  char **envp = new char *[environment.count() + 2];
537  envp[environment.count()] = 0;
538  envp[environment.count() + 1] = 0;
539 
542  for ( ; it != end; ++it) {
543  QByteArray key = it.key().key;
544  QByteArray value = it.value().bytes();
545  key.reserve(key.length() + 1 + value.length());
546  key.append('=');
547  key.append(value);
548 
549  envp[(*envc)++] = ::strdup(key.constData());
550  }
551 
552  if (needToAddLibraryPath)
553  envp[(*envc)++] = ::strdup(QByteArray(QByteArray(libraryPath) + '=' +
554  envLibraryPath).constData());
555  return envp;
556 }
557 
558 #ifdef Q_OS_MAC
559 Q_GLOBAL_STATIC(QMutex, cfbundleMutex);
560 #endif
561 
563 {
564  Q_Q(QProcess);
565 
566 #if defined (QPROCESS_DEBUG)
567  qDebug("QProcessPrivate::startProcess()");
568 #endif
569 
570  processManager()->start();
571 
572  // Initialize pipes
573  if (!createChannel(stdinChannel) ||
574  !createChannel(stdoutChannel) ||
575  !createChannel(stderrChannel) ||
576  qt_create_pipe(childStartedPipe) != 0 ||
577  qt_create_pipe(deathPipe) != 0) {
578  processError = QProcess::FailedToStart;
579  q->setErrorString(qt_error_string(errno));
580  emit q->error(processError);
581  cleanup();
582  return;
583  }
584 
585  if (threadData->eventDispatcher) {
586  startupSocketNotifier = new QSocketNotifier(childStartedPipe[0],
588  QObject::connect(startupSocketNotifier, SIGNAL(activated(int)),
589  q, SLOT(_q_startupNotification()));
590  deathNotifier = new QSocketNotifier(deathPipe[0],
592  QObject::connect(deathNotifier, SIGNAL(activated(int)),
593  q, SLOT(_q_processDied()));
594  }
595 
596  // Start the process (platform dependent)
597  q->setProcessState(QProcess::Starting);
598 
599  // Create argument list with right number of elements, and set the final
600  // one to 0.
601  char **argv = new char *[arguments.count() + 2];
602  argv[arguments.count() + 1] = 0;
603 
604  // Encode the program name.
605  QByteArray encodedProgramName = QFile::encodeName(program);
606 #ifdef Q_OS_MAC
607  // allow invoking of .app bundles on the Mac.
608  QFileInfo fileInfo(QString::fromUtf8(encodedProgramName.constData()));
609  if (encodedProgramName.endsWith(".app") && fileInfo.isDir()) {
610  QCFType<CFURLRef> url = CFURLCreateWithFileSystemPath(0,
611  QCFString(fileInfo.absoluteFilePath()),
612  kCFURLPOSIXPathStyle, true);
613  {
614  // CFBundle is not reentrant, since CFBundleCreate might return a reference
615  // to a cached bundle object. Protect the bundle calls with a mutex lock.
616  QMutexLocker lock(cfbundleMutex());
617  QCFType<CFBundleRef> bundle = CFBundleCreate(0, url);
618  url = CFBundleCopyExecutableURL(bundle);
619  }
620  if (url) {
621  QCFString str = CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle);
622  encodedProgramName += "/Contents/MacOS/" + static_cast<QString>(str).toUtf8();
623  }
624  }
625 #endif
626 
627  // Add the program name to the argument list.
628  char *dupProgramName = ::strdup(encodedProgramName.constData());
629  argv[0] = dupProgramName;
630 
631  // Add every argument to the list
632  for (int i = 0; i < arguments.count(); ++i) {
633  QString arg = arguments.at(i);
634 #ifdef Q_OS_MAC
635  // Mac OS X uses UTF8 for exec, regardless of the system locale.
636  argv[i + 1] = ::strdup(arg.toUtf8().constData());
637 #else
638  argv[i + 1] = ::strdup(arg.toLocal8Bit().constData());
639 #endif
640  }
641 
642  // Duplicate the environment.
643  int envc = 0;
644  char **envp = 0;
645  if (environment.d.constData()) {
646  QProcessEnvironmentPrivate::MutexLocker locker(environment.d);
647  envp = _q_dupEnvironment(environment.d.constData()->hash, &envc);
648  }
649 
650  // Encode the working directory if it's non-empty, otherwise just pass 0.
651  const char *workingDirPtr = 0;
652  QByteArray encodedWorkingDirectory;
653  if (!workingDirectory.isEmpty()) {
654  encodedWorkingDirectory = QFile::encodeName(workingDirectory);
655  workingDirPtr = encodedWorkingDirectory.constData();
656  }
657 
658  // If the program does not specify a path, generate a list of possible
659  // locations for the binary using the PATH environment variable.
660  char **path = 0;
661  int pathc = 0;
662  if (!program.contains(QLatin1Char('/'))) {
663  const QString pathEnv = QString::fromLocal8Bit(::getenv("PATH"));
664  if (!pathEnv.isEmpty()) {
665  QStringList pathEntries = pathEnv.split(QLatin1Char(':'), QString::SkipEmptyParts);
666  if (!pathEntries.isEmpty()) {
667  pathc = pathEntries.size();
668  path = new char *[pathc + 1];
669  path[pathc] = 0;
670 
671  for (int k = 0; k < pathEntries.size(); ++k) {
672  QByteArray tmp = QFile::encodeName(pathEntries.at(k));
673  if (!tmp.endsWith('/')) tmp += '/';
674  tmp += encodedProgramName;
675  path[k] = ::strdup(tmp.constData());
676  }
677  }
678  }
679  }
680 
681  // Start the process manager, and fork off the child process.
682  processManager()->lock();
683 #if defined(Q_OS_QNX)
684  pid_t childPid = spawnChild(workingDirPtr, argv, envp);
685 #else
686  pid_t childPid = fork();
687  int lastForkErrno = errno;
688 #endif
689  if (childPid != 0) {
690  // Clean up duplicated memory.
691  free(dupProgramName);
692  for (int i = 1; i <= arguments.count(); ++i)
693  free(argv[i]);
694  for (int i = 0; i < envc; ++i)
695  free(envp[i]);
696  for (int i = 0; i < pathc; ++i)
697  free(path[i]);
698  delete [] argv;
699  delete [] envp;
700  delete [] path;
701  }
702 
703  // This is not a valid check under QNX, because the semantics are
704  // different. While under other platforms where fork() may succeed and exec() can still fail,
705  // causing the childPid to hold a valid value (and thus evaluating the
706  // following if to false), and then signaling the error via
707  // childStartedPipe, under QNX on the other hand, spawn() return value will be assigned
708  // to childPid (which will be -1 in case of failure). This will force
709  // QProcess to cleanup, instead of signaling the error via
710  // childStartedPipe. Since it will invalidade the pipes, functions like
711  // QProcess::waitForStarted() will fail, for childStartedPipe will be
712  // '-1' and mess with the select() calls.
713 #if !defined(Q_OS_QNX)
714  if (childPid < 0) {
715  // Cleanup, report error and return
716 #if defined (QPROCESS_DEBUG)
717  qDebug("fork() failed: %s", qPrintable(qt_error_string(lastForkErrno)));
718 #endif
719  processManager()->unlock();
720  q->setProcessState(QProcess::NotRunning);
721  processError = QProcess::FailedToStart;
722  q->setErrorString(QProcess::tr("Resource error (fork failure): %1").arg(qt_error_string(lastForkErrno)));
723  emit q->error(processError);
724  cleanup();
725  return;
726  }
727 
728  // Start the child.
729  if (childPid == 0) {
730  execChild(workingDirPtr, path, argv, envp);
731  ::_exit(-1);
732  }
733 #endif
734 
735  // Register the child. In the mean time, we can get a SIGCHLD, so we need
736  // to keep the lock held to avoid a race to catch the child.
737  processManager()->add(childPid, q);
738  pid = Q_PID(childPid);
739  processManager()->unlock();
740 
741  // parent
742  // close the ends we don't use and make all pipes non-blocking
743  ::fcntl(deathPipe[0], F_SETFL, ::fcntl(deathPipe[0], F_GETFL) | O_NONBLOCK);
744  qt_safe_close(childStartedPipe[1]);
745  childStartedPipe[1] = -1;
746 
747  if (stdinChannel.pipe[0] != -1) {
748  qt_safe_close(stdinChannel.pipe[0]);
749  stdinChannel.pipe[0] = -1;
750  }
751  if (stdinChannel.pipe[1] != -1)
752  ::fcntl(stdinChannel.pipe[1], F_SETFL, ::fcntl(stdinChannel.pipe[1], F_GETFL) | O_NONBLOCK);
753 
754  if (stdoutChannel.pipe[1] != -1) {
755  qt_safe_close(stdoutChannel.pipe[1]);
756  stdoutChannel.pipe[1] = -1;
757  }
758  if (stdoutChannel.pipe[0] != -1)
759  ::fcntl(stdoutChannel.pipe[0], F_SETFL, ::fcntl(stdoutChannel.pipe[0], F_GETFL) | O_NONBLOCK);
760 
761  if (stderrChannel.pipe[1] != -1) {
762  qt_safe_close(stderrChannel.pipe[1]);
763  stderrChannel.pipe[1] = -1;
764  }
765  if (stderrChannel.pipe[0] != -1)
766  ::fcntl(stderrChannel.pipe[0], F_SETFL, ::fcntl(stderrChannel.pipe[0], F_GETFL) | O_NONBLOCK);
767 }
768 
769 #if !defined(Q_OS_QNX)
770 void QProcessPrivate::execChild(const char *workingDir, char **path, char **argv, char **envp)
771 {
772  ::signal(SIGPIPE, SIG_DFL); // reset the signal that we ignored
773 
774  Q_Q(QProcess);
775 
776  // copy the stdin socket (without closing on exec)
777  qt_safe_dup2(stdinChannel.pipe[0], STDIN_FILENO, 0);
778 
779  // copy the stdout and stderr if asked to
780  if (processChannelMode != QProcess::ForwardedChannels) {
781  qt_safe_dup2(stdoutChannel.pipe[1], STDOUT_FILENO, 0);
782 
783  // merge stdout and stderr if asked to
784  if (processChannelMode == QProcess::MergedChannels) {
785  qt_safe_dup2(STDOUT_FILENO, STDERR_FILENO, 0);
786  } else {
787  qt_safe_dup2(stderrChannel.pipe[1], STDERR_FILENO, 0);
788  }
789  }
790 
791  // make sure this fd is closed if execvp() succeeds
792  qt_safe_close(childStartedPipe[0]);
793 
794  // enter the working directory
795  if (workingDir)
796  QT_CHDIR(workingDir);
797 
798  // this is a virtual call, and it base behavior is to do nothing.
799  q->setupChildProcess();
800 
801  // execute the process
802  if (!envp) {
803  qt_safe_execvp(argv[0], argv);
804  } else {
805  if (path) {
806  char **arg = path;
807  while (*arg) {
808  argv[0] = *arg;
809 #if defined (QPROCESS_DEBUG)
810  fprintf(stderr, "QProcessPrivate::execChild() searching / starting %s\n", argv[0]);
811 #endif
812  qt_safe_execve(argv[0], argv, envp);
813  ++arg;
814  }
815  } else {
816 #if defined (QPROCESS_DEBUG)
817  fprintf(stderr, "QProcessPrivate::execChild() starting %s\n", argv[0]);
818 #endif
819  qt_safe_execve(argv[0], argv, envp);
820  }
821  }
822 
823  // notify failure
825 #if defined (QPROCESS_DEBUG)
826  fprintf(stderr, "QProcessPrivate::execChild() failed (%s), notifying parent process\n", qPrintable(error));
827 #endif
828  qt_safe_write(childStartedPipe[1], error.data(), error.length() * sizeof(QChar));
829  qt_safe_close(childStartedPipe[1]);
830  childStartedPipe[1] = -1;
831 }
832 
833 #endif //Q_OS_QNX
834 
836 {
837  ushort buf[errorBufferMax];
838  int i = qt_safe_read(childStartedPipe[0], &buf, sizeof buf);
839  if (startupSocketNotifier) {
840  startupSocketNotifier->setEnabled(false);
841  startupSocketNotifier->deleteLater();
842  startupSocketNotifier = 0;
843  }
844  qt_safe_close(childStartedPipe[0]);
845  childStartedPipe[0] = -1;
846 
847 #if defined (QPROCESS_DEBUG)
848  qDebug("QProcessPrivate::processStarted() == %s", i <= 0 ? "true" : "false");
849 #endif
850 
851  // did we read an error message?
852  if (i > 0)
853  q_func()->setErrorString(QString((const QChar *)buf, i / sizeof(QChar)));
854 
855  return i <= 0;
856 }
857 
858 #if defined(Q_OS_QNX)
859 static pid_t doSpawn(int fd_count, int fd_map[], char **argv, char **envp,
860  const char *workingDir, bool spawn_detached)
861 {
862  // A multi threaded QNX Process can't fork so we call spawn() instead.
863 
864  struct inheritance inherit;
865  memset(&inherit, 0, sizeof(inherit));
866  inherit.flags |= SPAWN_SETSID;
867  inherit.flags |= SPAWN_CHECK_SCRIPT;
868  if (spawn_detached)
869  inherit.flags |= SPAWN_NOZOMBIE;
870  inherit.flags |= SPAWN_SETSIGDEF;
871  sigaddset(&inherit.sigdefault, SIGPIPE); // reset the signal that we ignored
872 
873  // enter the working directory
874  const char *oldWorkingDir = 0;
875  char buff[PATH_MAX + 1];
876 
877  if (workingDir) {
878  //we need to freeze everyone in order to avoid race conditions with //chdir().
879  if (ThreadCtl(_NTO_TCTL_THREADS_HOLD, 0) == -1)
880  qWarning("ThreadCtl(): cannot hold threads: %s", qPrintable(qt_error_string(errno)));
881 
882  oldWorkingDir = QT_GETCWD(buff, PATH_MAX + 1);
883  QT_CHDIR(workingDir);
884  }
885 
886  pid_t childPid;
887  EINTR_LOOP(childPid, ::spawn(argv[0], fd_count, fd_map, &inherit, argv, envp));
888  if (childPid == -1) {
889  inherit.flags |= SPAWN_SEARCH_PATH;
890  EINTR_LOOP(childPid, ::spawn(argv[0], fd_count, fd_map, &inherit, argv, envp));
891  }
892 
893  if (oldWorkingDir) {
894  QT_CHDIR(oldWorkingDir);
895 
896  if (ThreadCtl(_NTO_TCTL_THREADS_CONT, 0) == -1)
897  qFatal("ThreadCtl(): cannot resume threads: %s", qPrintable(qt_error_string(errno)));
898  }
899 
900  return childPid;
901 }
902 
903 pid_t QProcessPrivate::spawnChild(const char *workingDir, char **argv, char **envp)
904 {
905  // we need to manually fill in fd_map
906  // to inherit the file descriptors from
907  // the parent
908  const int fd_count = sysconf(_SC_OPEN_MAX);
909  QVarLengthArray<int, 1024> fd_map(fd_count);
910 
911  for (int i = 3; i < fd_count; ++i) {
912  // here we rely that fcntl returns -1 and
913  // sets errno to EBADF
914  const int flags = ::fcntl(i, F_GETFD);
915 
916  fd_map[i] = ((flags >= 0) && !(flags & FD_CLOEXEC))
917  ? i : SPAWN_FDCLOSED;
918  }
919 
920  switch (processChannelMode) {
922  fd_map[0] = stdinChannel.pipe[0];
923  fd_map[1] = QT_FILENO(stdout);
924  fd_map[2] = QT_FILENO(stderr);
925  break;
927  fd_map[0] = stdinChannel.pipe[0];
928  fd_map[1] = stdoutChannel.pipe[1];
929  fd_map[2] = stdoutChannel.pipe[1];
930  break;
932  fd_map[0] = stdinChannel.pipe[0];
933  fd_map[1] = stdoutChannel.pipe[1];
934  fd_map[2] = stderrChannel.pipe[1];
935  break;
936  }
937 
938  pid_t childPid = doSpawn(fd_count, fd_map.data(), argv, envp, workingDir, false);
939 
940  if (childPid == -1) {
942  qt_safe_write(childStartedPipe[1], error.data(), error.length() * sizeof(QChar));
943  qt_safe_close(childStartedPipe[1]);
944  childStartedPipe[1] = -1;
945  }
946 
947  return childPid;
948 }
949 #endif // Q_OS_QNX
950 
952 {
953  int nbytes = 0;
954  qint64 available = 0;
955  if (::ioctl(stdoutChannel.pipe[0], FIONREAD, (char *) &nbytes) >= 0)
956  available = (qint64) nbytes;
957 #if defined (QPROCESS_DEBUG)
958  qDebug("QProcessPrivate::bytesAvailableFromStdout() == %lld", available);
959 #endif
960  return available;
961 }
962 
964 {
965  int nbytes = 0;
966  qint64 available = 0;
967  if (::ioctl(stderrChannel.pipe[0], FIONREAD, (char *) &nbytes) >= 0)
968  available = (qint64) nbytes;
969 #if defined (QPROCESS_DEBUG)
970  qDebug("QProcessPrivate::bytesAvailableFromStderr() == %lld", available);
971 #endif
972  return available;
973 }
974 
976 {
977  qint64 bytesRead = qt_safe_read(stdoutChannel.pipe[0], data, maxlen);
978 #if defined QPROCESS_DEBUG
979  qDebug("QProcessPrivate::readFromStdout(%p \"%s\", %lld) == %lld",
980  data, qt_prettyDebug(data, bytesRead, 16).constData(), maxlen, bytesRead);
981 #endif
982  return bytesRead;
983 }
984 
986 {
987  qint64 bytesRead = qt_safe_read(stderrChannel.pipe[0], data, maxlen);
988 #if defined QPROCESS_DEBUG
989  qDebug("QProcessPrivate::readFromStderr(%p \"%s\", %lld) == %lld",
990  data, qt_prettyDebug(data, bytesRead, 16).constData(), maxlen, bytesRead);
991 #endif
992  return bytesRead;
993 }
994 
995 qint64 QProcessPrivate::writeToStdin(const char *data, qint64 maxlen)
996 {
997  qint64 written = qt_safe_write_nosignal(stdinChannel.pipe[1], data, maxlen);
998 #if defined QPROCESS_DEBUG
999  qDebug("QProcessPrivate::writeToStdin(%p \"%s\", %lld) == %lld",
1000  data, qt_prettyDebug(data, maxlen, 16).constData(), maxlen, written);
1001  if (written == -1)
1002  qDebug("QProcessPrivate::writeToStdin(), failed to write (%s)", qPrintable(qt_error_string(errno)));
1003 #endif
1004  // If the O_NONBLOCK flag is set and If some data can be written without blocking
1005  // the process, write() will transfer what it can and return the number of bytes written.
1006  // Otherwise, it will return -1 and set errno to EAGAIN
1007  if (written == -1 && errno == EAGAIN)
1008  written = 0;
1009  return written;
1010 }
1011 
1013 {
1014 #if defined (QPROCESS_DEBUG)
1015  qDebug("QProcessPrivate::killProcess()");
1016 #endif
1017  if (pid)
1018  ::kill(pid_t(pid), SIGTERM);
1019 }
1020 
1022 {
1023 #if defined (QPROCESS_DEBUG)
1024  qDebug("QProcessPrivate::killProcess()");
1025 #endif
1026  if (pid)
1027  ::kill(pid_t(pid), SIGKILL);
1028 }
1029 
1030 static int select_msecs(int nfds, fd_set *fdread, fd_set *fdwrite, int timeout)
1031 {
1032  if (timeout < 0)
1033  return qt_safe_select(nfds, fdread, fdwrite, 0, 0);
1034 
1035  struct timeval tv;
1036  tv.tv_sec = timeout / 1000;
1037  tv.tv_usec = (timeout % 1000) * 1000;
1038  return qt_safe_select(nfds, fdread, fdwrite, 0, &tv);
1039 }
1040 
1041 /*
1042  Returns the difference between msecs and elapsed. If msecs is -1,
1043  however, -1 is returned.
1044 */
1045 static int qt_timeout_value(int msecs, int elapsed)
1046 {
1047  if (msecs == -1)
1048  return -1;
1049 
1050  int timeout = msecs - elapsed;
1051  return timeout < 0 ? 0 : timeout;
1052 }
1053 
1055 {
1056  Q_Q(QProcess);
1057 
1058 #if defined (QPROCESS_DEBUG)
1059  qDebug("QProcessPrivate::waitForStarted(%d) waiting for child to start (fd = %d)", msecs,
1060  childStartedPipe[0]);
1061 #endif
1062 
1063  fd_set fds;
1064  FD_ZERO(&fds);
1065  FD_SET(childStartedPipe[0], &fds);
1066  if (select_msecs(childStartedPipe[0] + 1, &fds, 0, msecs) == 0) {
1067  processError = QProcess::Timedout;
1068  q->setErrorString(QProcess::tr("Process operation timed out"));
1069 #if defined (QPROCESS_DEBUG)
1070  qDebug("QProcessPrivate::waitForStarted(%d) == false (timed out)", msecs);
1071 #endif
1072  return false;
1073  }
1074 
1075  bool startedEmitted = _q_startupNotification();
1076 #if defined (QPROCESS_DEBUG)
1077  qDebug("QProcessPrivate::waitForStarted() == %s", startedEmitted ? "true" : "false");
1078 #endif
1079  return startedEmitted;
1080 }
1081 
1083 {
1084  Q_Q(QProcess);
1085 #if defined (QPROCESS_DEBUG)
1086  qDebug("QProcessPrivate::waitForReadyRead(%d)", msecs);
1087 #endif
1088 
1089  QElapsedTimer stopWatch;
1090  stopWatch.start();
1091 
1092  forever {
1093  fd_set fdread;
1094  fd_set fdwrite;
1095 
1096  FD_ZERO(&fdread);
1097  FD_ZERO(&fdwrite);
1098 
1099  int nfds = deathPipe[0];
1100  FD_SET(deathPipe[0], &fdread);
1101 
1102  if (processState == QProcess::Starting)
1103  add_fd(nfds, childStartedPipe[0], &fdread);
1104 
1105  if (stdoutChannel.pipe[0] != -1)
1106  add_fd(nfds, stdoutChannel.pipe[0], &fdread);
1107  if (stderrChannel.pipe[0] != -1)
1108  add_fd(nfds, stderrChannel.pipe[0], &fdread);
1109 
1110  if (!writeBuffer.isEmpty() && stdinChannel.pipe[1] != -1)
1111  add_fd(nfds, stdinChannel.pipe[1], &fdwrite);
1112 
1113  int timeout = qt_timeout_value(msecs, stopWatch.elapsed());
1114  int ret = select_msecs(nfds + 1, &fdread, &fdwrite, timeout);
1115  if (ret < 0) {
1116  break;
1117  }
1118  if (ret == 0) {
1119  processError = QProcess::Timedout;
1120  q->setErrorString(QProcess::tr("Process operation timed out"));
1121  return false;
1122  }
1123 
1124  if (childStartedPipe[0] != -1 && FD_ISSET(childStartedPipe[0], &fdread)) {
1125  if (!_q_startupNotification())
1126  return false;
1127  }
1128 
1129  bool readyReadEmitted = false;
1130  if (stdoutChannel.pipe[0] != -1 && FD_ISSET(stdoutChannel.pipe[0], &fdread)) {
1131  bool canRead = _q_canReadStandardOutput();
1132  if (processChannel == QProcess::StandardOutput && canRead)
1133  readyReadEmitted = true;
1134  }
1135  if (stderrChannel.pipe[0] != -1 && FD_ISSET(stderrChannel.pipe[0], &fdread)) {
1136  bool canRead = _q_canReadStandardError();
1137  if (processChannel == QProcess::StandardError && canRead)
1138  readyReadEmitted = true;
1139  }
1140  if (readyReadEmitted)
1141  return true;
1142 
1143  if (stdinChannel.pipe[1] != -1 && FD_ISSET(stdinChannel.pipe[1], &fdwrite))
1144  _q_canWrite();
1145 
1146  if (deathPipe[0] == -1 || FD_ISSET(deathPipe[0], &fdread)) {
1147  if (_q_processDied())
1148  return false;
1149  }
1150  }
1151  return false;
1152 }
1153 
1155 {
1156  Q_Q(QProcess);
1157 #if defined (QPROCESS_DEBUG)
1158  qDebug("QProcessPrivate::waitForBytesWritten(%d)", msecs);
1159 #endif
1160 
1161  QElapsedTimer stopWatch;
1162  stopWatch.start();
1163 
1164  while (!writeBuffer.isEmpty()) {
1165  fd_set fdread;
1166  fd_set fdwrite;
1167 
1168  FD_ZERO(&fdread);
1169  FD_ZERO(&fdwrite);
1170 
1171  int nfds = deathPipe[0];
1172  FD_SET(deathPipe[0], &fdread);
1173 
1174  if (processState == QProcess::Starting)
1175  add_fd(nfds, childStartedPipe[0], &fdread);
1176 
1177  if (stdoutChannel.pipe[0] != -1)
1178  add_fd(nfds, stdoutChannel.pipe[0], &fdread);
1179  if (stderrChannel.pipe[0] != -1)
1180  add_fd(nfds, stderrChannel.pipe[0], &fdread);
1181 
1182 
1183  if (!writeBuffer.isEmpty() && stdinChannel.pipe[1] != -1)
1184  add_fd(nfds, stdinChannel.pipe[1], &fdwrite);
1185 
1186  int timeout = qt_timeout_value(msecs, stopWatch.elapsed());
1187  int ret = select_msecs(nfds + 1, &fdread, &fdwrite, timeout);
1188  if (ret < 0) {
1189  break;
1190  }
1191 
1192  if (ret == 0) {
1193  processError = QProcess::Timedout;
1194  q->setErrorString(QProcess::tr("Process operation timed out"));
1195  return false;
1196  }
1197 
1198  if (childStartedPipe[0] != -1 && FD_ISSET(childStartedPipe[0], &fdread)) {
1199  if (!_q_startupNotification())
1200  return false;
1201  }
1202 
1203  if (stdinChannel.pipe[1] != -1 && FD_ISSET(stdinChannel.pipe[1], &fdwrite))
1204  return _q_canWrite();
1205 
1206  if (stdoutChannel.pipe[0] != -1 && FD_ISSET(stdoutChannel.pipe[0], &fdread))
1207  _q_canReadStandardOutput();
1208 
1209  if (stderrChannel.pipe[0] != -1 && FD_ISSET(stderrChannel.pipe[0], &fdread))
1210  _q_canReadStandardError();
1211 
1212  if (deathPipe[0] == -1 || FD_ISSET(deathPipe[0], &fdread)) {
1213  if (_q_processDied())
1214  return false;
1215  }
1216  }
1217 
1218  return false;
1219 }
1220 
1222 {
1223  Q_Q(QProcess);
1224 #if defined (QPROCESS_DEBUG)
1225  qDebug("QProcessPrivate::waitForFinished(%d)", msecs);
1226 #endif
1227 
1228  QElapsedTimer stopWatch;
1229  stopWatch.start();
1230 
1231  forever {
1232  fd_set fdread;
1233  fd_set fdwrite;
1234  int nfds = -1;
1235 
1236  FD_ZERO(&fdread);
1237  FD_ZERO(&fdwrite);
1238 
1239  if (processState == QProcess::Starting)
1240  add_fd(nfds, childStartedPipe[0], &fdread);
1241 
1242  if (stdoutChannel.pipe[0] != -1)
1243  add_fd(nfds, stdoutChannel.pipe[0], &fdread);
1244  if (stderrChannel.pipe[0] != -1)
1245  add_fd(nfds, stderrChannel.pipe[0], &fdread);
1246 
1247  if (processState == QProcess::Running)
1248  add_fd(nfds, deathPipe[0], &fdread);
1249 
1250  if (!writeBuffer.isEmpty() && stdinChannel.pipe[1] != -1)
1251  add_fd(nfds, stdinChannel.pipe[1], &fdwrite);
1252 
1253  int timeout = qt_timeout_value(msecs, stopWatch.elapsed());
1254  int ret = select_msecs(nfds + 1, &fdread, &fdwrite, timeout);
1255  if (ret < 0) {
1256  break;
1257  }
1258  if (ret == 0) {
1259  processError = QProcess::Timedout;
1260  q->setErrorString(QProcess::tr("Process operation timed out"));
1261  return false;
1262  }
1263 
1264  if (childStartedPipe[0] != -1 && FD_ISSET(childStartedPipe[0], &fdread)) {
1265  if (!_q_startupNotification())
1266  return false;
1267  }
1268  if (stdinChannel.pipe[1] != -1 && FD_ISSET(stdinChannel.pipe[1], &fdwrite))
1269  _q_canWrite();
1270 
1271  if (stdoutChannel.pipe[0] != -1 && FD_ISSET(stdoutChannel.pipe[0], &fdread))
1272  _q_canReadStandardOutput();
1273 
1274  if (stderrChannel.pipe[0] != -1 && FD_ISSET(stderrChannel.pipe[0], &fdread))
1275  _q_canReadStandardError();
1276 
1277  if (deathPipe[0] == -1 || FD_ISSET(deathPipe[0], &fdread)) {
1278  if (_q_processDied())
1279  return true;
1280  }
1281  }
1282  return false;
1283 }
1284 
1286 {
1287  fd_set fdwrite;
1288  FD_ZERO(&fdwrite);
1289  FD_SET(stdinChannel.pipe[1], &fdwrite);
1290  return select_msecs(stdinChannel.pipe[1] + 1, 0, &fdwrite, msecs < 0 ? 0 : msecs) == 1;
1291 }
1292 
1294 {
1295  Q_Q(QProcess);
1296  processManager()->remove(q);
1297 }
1298 
1300 {
1301  Q_Q(QProcess);
1302 
1303  // read a byte from the death pipe
1304  char c;
1305  qt_safe_read(deathPipe[0], &c, 1);
1306 
1307  // check if our process is dead
1308  int exitStatus;
1309  if (qt_safe_waitpid(pid_t(pid), &exitStatus, WNOHANG) > 0) {
1310  processManager()->remove(q);
1311  crashed = !WIFEXITED(exitStatus);
1312  exitCode = WEXITSTATUS(exitStatus);
1313 #if defined QPROCESS_DEBUG
1314  qDebug() << "QProcessPrivate::waitForDeadChild() dead with exitCode"
1315  << exitCode << ", crashed?" << crashed;
1316 #endif
1317  return true;
1318  }
1319 #if defined QPROCESS_DEBUG
1320  qDebug() << "QProcessPrivate::waitForDeadChild() not dead!";
1321 #endif
1322  return false;
1323 }
1324 
1326 {
1327 }
1328 
1329 #if defined(Q_OS_QNX)
1330 bool QProcessPrivate::startDetached(const QString &program, const QStringList &arguments, const QString &workingDirectory, qint64 *pid)
1331 {
1332  const int fd_count = 3;
1333  int fd_map[fd_count] = { QT_FILENO(stdin), QT_FILENO(stdout), QT_FILENO(stderr) };
1334 
1335  QList<QByteArray> enc_args;
1336  enc_args.append(QFile::encodeName(program));
1337  for (int i = 0; i < arguments.size(); ++i)
1338  enc_args.append(arguments.at(i).toLocal8Bit());
1339 
1340  const int argc = enc_args.size();
1341  QScopedArrayPointer<char*> raw_argv(new char*[argc + 1]);
1342  for (int i = 0; i < argc; ++i)
1343  raw_argv[i] = const_cast<char *>(enc_args.at(i).data());
1344  raw_argv[argc] = 0;
1345 
1346  char **envp = 0; // inherit environment
1347 
1348  // Encode the working directory if it's non-empty, otherwise just pass 0.
1349  const char *workingDirPtr = 0;
1350  QByteArray encodedWorkingDirectory;
1351  if (!workingDirectory.isEmpty()) {
1352  encodedWorkingDirectory = QFile::encodeName(workingDirectory);
1353  workingDirPtr = encodedWorkingDirectory.constData();
1354  }
1355 
1356  pid_t childPid = doSpawn(fd_count, fd_map, raw_argv.data(), envp, workingDirPtr, true);
1357  if (pid && childPid != -1)
1358  *pid = childPid;
1359 
1360  return childPid != -1;
1361 }
1362 
1363 #else
1364 
1365 bool QProcessPrivate::startDetached(const QString &program, const QStringList &arguments, const QString &workingDirectory, qint64 *pid)
1366 {
1367  processManager()->start();
1368 
1369  QByteArray encodedWorkingDirectory = QFile::encodeName(workingDirectory);
1370 
1371  // To catch the startup of the child
1372  int startedPipe[2];
1373  if (qt_safe_pipe(startedPipe) != 0)
1374  return false;
1375  // To communicate the pid of the child
1376  int pidPipe[2];
1377  if (qt_safe_pipe(pidPipe) != 0) {
1378  qt_safe_close(startedPipe[0]);
1379  qt_safe_close(startedPipe[1]);
1380  return false;
1381  }
1382 
1383  pid_t childPid = fork();
1384  if (childPid == 0) {
1385  struct sigaction noaction;
1386  memset(&noaction, 0, sizeof(noaction));
1387  noaction.sa_handler = SIG_IGN;
1388  ::sigaction(SIGPIPE, &noaction, 0);
1389 
1390  ::setsid();
1391 
1392  qt_safe_close(startedPipe[0]);
1393  qt_safe_close(pidPipe[0]);
1394 
1395  pid_t doubleForkPid = fork();
1396  if (doubleForkPid == 0) {
1397  qt_safe_close(pidPipe[1]);
1398 
1399  if (!encodedWorkingDirectory.isEmpty())
1400  QT_CHDIR(encodedWorkingDirectory.constData());
1401 
1402  char **argv = new char *[arguments.size() + 2];
1403  for (int i = 0; i < arguments.size(); ++i) {
1404 #ifdef Q_OS_MAC
1405  argv[i + 1] = ::strdup(arguments.at(i).toUtf8().constData());
1406 #else
1407  argv[i + 1] = ::strdup(arguments.at(i).toLocal8Bit().constData());
1408 #endif
1409  }
1410  argv[arguments.size() + 1] = 0;
1411 
1412  if (!program.contains(QLatin1Char('/'))) {
1413  const QString path = QString::fromLocal8Bit(::getenv("PATH"));
1414  if (!path.isEmpty()) {
1415  QStringList pathEntries = path.split(QLatin1Char(':'));
1416  for (int k = 0; k < pathEntries.size(); ++k) {
1417  QByteArray tmp = QFile::encodeName(pathEntries.at(k));
1418  if (!tmp.endsWith('/')) tmp += '/';
1419  tmp += QFile::encodeName(program);
1420  argv[0] = tmp.data();
1421  qt_safe_execv(argv[0], argv);
1422  }
1423  }
1424  } else {
1425  QByteArray tmp = QFile::encodeName(program);
1426  argv[0] = tmp.data();
1427  qt_safe_execv(argv[0], argv);
1428  }
1429 
1430  struct sigaction noaction;
1431  memset(&noaction, 0, sizeof(noaction));
1432  noaction.sa_handler = SIG_IGN;
1433  ::sigaction(SIGPIPE, &noaction, 0);
1434 
1435  // '\1' means execv failed
1436  char c = '\1';
1437  qt_safe_write(startedPipe[1], &c, 1);
1438  qt_safe_close(startedPipe[1]);
1439  ::_exit(1);
1440  } else if (doubleForkPid == -1) {
1441  struct sigaction noaction;
1442  memset(&noaction, 0, sizeof(noaction));
1443  noaction.sa_handler = SIG_IGN;
1444  ::sigaction(SIGPIPE, &noaction, 0);
1445 
1446  // '\2' means internal error
1447  char c = '\2';
1448  qt_safe_write(startedPipe[1], &c, 1);
1449  }
1450 
1451  qt_safe_close(startedPipe[1]);
1452  qt_safe_write(pidPipe[1], (const char *)&doubleForkPid, sizeof(pid_t));
1453  QT_CHDIR("/");
1454  ::_exit(1);
1455  }
1456 
1457  qt_safe_close(startedPipe[1]);
1458  qt_safe_close(pidPipe[1]);
1459 
1460  if (childPid == -1) {
1461  qt_safe_close(startedPipe[0]);
1462  qt_safe_close(pidPipe[0]);
1463  return false;
1464  }
1465 
1466  char reply = '\0';
1467  int startResult = qt_safe_read(startedPipe[0], &reply, 1);
1468  int result;
1469  qt_safe_close(startedPipe[0]);
1470  qt_safe_waitpid(childPid, &result, 0);
1471  bool success = (startResult != -1 && reply == '\0');
1472  if (success && pid) {
1473  pid_t actualPid = 0;
1474  if (qt_safe_read(pidPipe[0], (char *)&actualPid, sizeof(pid_t)) == sizeof(pid_t)) {
1475  *pid = actualPid;
1476  } else {
1477  *pid = 0;
1478  }
1479  }
1480  qt_safe_close(pidPipe[0]);
1481  return success;
1482 }
1483 #endif // Q_OS_QNX
1484 
1486 {
1487  (void) processManager();
1488 }
1489 
1491 
1492 #include "qprocess_unix.moc"
1493 
1494 #endif // QT_NO_PROCESS
The QProcessEnvironment class holds the environment variables that can be passed to a program...
Definition: qprocess.h:68
QBool contains(QChar c, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition: qstring.h:904
QString qt_error_string(int errorCode)
Definition: qglobal.cpp:2600
Q_CORE_EXPORT QByteArray qgetenv(const char *varName)
QString & sprintf(const char *format,...)
Safely builds a formatted string from the format string cformat and an arbitrary list of arguments...
Definition: qstring.cpp:5567
static int qt_qprocess_deadChild_pipe[2]
static QString fromLocal8Bit(const char *, int size=-1)
Returns a QString initialized with the first size characters of the 8-bit string str.
Definition: qstring.cpp:4245
static mach_timebase_info_data_t info
unsigned char c[8]
Definition: qnumeric_p.h:62
static double elapsed(qint64 after, qint64 before)
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
The QMutex class provides access serialization between threads.
Definition: qmutex.h:60
char * data()
Returns a pointer to the data stored in the byte array.
Definition: qbytearray.h:429
const QChar at(int i) const
Returns the character at the given index position in the string.
Definition: qstring.h:698
#define add(aName)
#define EINTR_LOOP(var, cmd)
Definition: qcore_unix_p.h:96
T * data() const
Returns the value of the pointer referenced by this object.
#define it(className, varName)
QByteArray & append(char c)
Appends the character ch to this byte array.
QByteArray toUtf8() const Q_REQUIRED_RESULT
Returns a UTF-8 representation of the string as a QByteArray.
Definition: qstring.cpp:4074
#define error(msg)
static struct sigaction qt_sa_old_sigchld_handler
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:135
static int qt_safe_execvp(const char *file, char *const argv[])
Definition: qcore_unix_p.h:324
qint64 bytesAvailableFromStdout() const
int length() const
Returns the number of characters in this string.
Definition: qstring.h:696
#define SLOT(a)
Definition: qobjectdefs.h:226
#define O_RDONLY
const_iterator ConstIterator
Qt-style synonym for QHash::const_iterator.
Definition: qhash.h:474
static const int errorBufferMax
int select(int, fd_set *, fd_set *, fd_set *, struct timeval *)
#define O_TRUNC
Channel stdinChannel
Definition: qprocess_p.h:317
static bool startDetached(const QString &program, const QStringList &arguments, const QString &workingDirectory=QString(), qint64 *pid=0)
QString absoluteFilePath() const
Returns an absolute path including the file name.
Definition: qfileinfo.cpp:534
#define QT_END_INCLUDE_NAMESPACE
This macro is equivalent to QT_BEGIN_NAMESPACE.
Definition: qglobal.h:92
static QString tr(const char *sourceText, const char *comment=0, int n=-1)
T & value() const
Returns a modifiable reference to the current item&#39;s value.
Definition: qhash.h:348
QSharedDataPointer< QProcessEnvironmentPrivate > d
Definition: qprocess.h:99
static int qt_safe_close(int fd)
Definition: qcore_unix_p.h:297
void run()
The starting point for the thread.
The QString class provides a Unicode character string.
Definition: qstring.h:83
The QHash class is a template class that provides a hash-table-based dictionary.
Definition: qdatastream.h:66
Q_GLOBAL_STATIC(QMutex, cfbundleMutex)
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
#define Q_BASIC_ATOMIC_INITIALIZER(a)
Definition: qbasicatomic.h:218
qint64 bytesAvailableFromStderr() const
#define INVALID_Q_PIPE
Definition: qprocess_p.h:69
#define O_CREAT
qint64 writeToStdin(const char *data, qint64 maxlen)
The QElapsedTimer class provides a fast way to calculate elapsed times.
Definition: qelapsedtimer.h:53
bool contains(const Key &key) const
Returns true if the hash contains an item with the key; otherwise returns false.
Definition: qhash.h:872
The QChar class provides a 16-bit Unicode character.
Definition: qchar.h:72
QChar * data()
Returns a pointer to the data stored in the QString.
Definition: qstring.h:710
qint64 elapsed() const
Returns the number of milliseconds since this QElapsedTimer was last started.
#define O_APPEND
static int qt_timeout_value(int msecs, int elapsed)
bool waitForReadyRead(int msecs=30000)
bool waitForWrite(int msecs=30000)
bool isEmpty() const
Returns true if the list contains no items; otherwise returns false.
Definition: qlist.h:152
QSocketNotifier * notifier
Definition: qprocess_p.h:286
iterator insert(const Key &key, const T &value)
Inserts a new item with the key and a value of value.
Definition: qhash.h:753
The QSocketNotifier class provides support for monitoring activity on a file descriptor.
#define Q_Q(Class)
Definition: qglobal.h:2483
Q_CORE_EXPORT void qDebug(const char *,...)
static int qt_safe_execve(const char *filename, char *const argv[], char *const envp[])
Definition: qcore_unix_p.h:309
#define SIGNAL(a)
Definition: qobjectdefs.h:227
static char ** _q_dupEnvironment(const QProcessEnvironmentPrivate::Hash &environment, int *envc)
void append(const T &t)
Inserts value at the end of the list.
Definition: qlist.h:507
qint64 readFromStdout(char *data, qint64 maxlen)
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
static void initializeProcessManager()
static int qt_safe_open(const char *pathname, int flags, mode_t mode=0777)
Definition: qcore_unix_p.h:171
bool waitForStarted(int msecs=30000)
bool isDir() const
Returns true if this object points to a directory or to a symbolic link to a directory; otherwise ret...
Definition: qfileinfo.cpp:990
static bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
Creates a connection of the given type from the signal in the sender object to the method in the rece...
Definition: qobject.cpp:2580
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition: qstring.h:704
const char * name
Channel stdoutChannel
Definition: qprocess_p.h:318
const T & at(int i) const
Returns the item at index position i in the list.
Definition: qlist.h:468
#define emit
Definition: qobjectdefs.h:76
The QStringList class provides a list of strings.
Definition: qstringlist.h:66
static QString fromUtf8(const char *, int size=-1)
Returns a QString initialized with the first size bytes of the UTF-8 string str.
Definition: qstring.cpp:4302
bool isEmpty() const
Returns true if the hash contains no items; otherwise returns false.
Definition: qhash.h:297
Q_CORE_EXPORT void qWarning(const char *,...)
QHash< int, QProcessInfo * > children
static int qt_safe_dup2(int oldfd, int newfd, int flags=FD_CLOEXEC)
Definition: qcore_unix_p.h:251
static const char * data(const QByteArray &arr)
static int qt_safe_pipe(int pipefd[2], int flags=0)
Definition: qcore_unix_p.h:191
static QProcessEnvironment systemEnvironment()
The systemEnvironment function returns the environment of the calling process.
void add(pid_t pid, QProcess *process)
static int qt_safe_execv(const char *path, char *const argv[])
Definition: qcore_unix_p.h:317
QByteArray toLatin1() const Q_REQUIRED_RESULT
Returns a Latin-1 representation of the string as a QByteArray.
Definition: qstring.cpp:3993
__int64 qint64
Definition: qglobal.h:942
#define PATH_MAX
qint64 readFromStderr(char *data, qint64 maxlen)
static int qt_create_pipe(int *pipe)
The QScopedArrayPointer class stores a pointer to a dynamically allocated array of objects...
QByteArray toLocal8Bit() const Q_REQUIRED_RESULT
Returns the local 8-bit representation of the string as a QByteArray.
Definition: qstring.cpp:4049
static QBasicAtomicInt idCounter
#define Q_OBJECT
Definition: qobjectdefs.h:157
QProcessPrivate * process
Definition: qprocess_p.h:285
int length() const
Same as size().
Definition: qbytearray.h:356
const char * constData() const
Returns a pointer to the data stored in the byte array.
Definition: qbytearray.h:433
const_iterator constBegin() const
Returns a const STL-style iterator pointing to the first item in the hash.
Definition: qhash.h:466
const_iterator constEnd() const
Returns a const STL-style iterator pointing to the imaginary item after the last item in the hash...
Definition: qhash.h:469
qint64 Q_PID
Definition: qprocess.h:58
Q_CORE_EXPORT void qFatal(const char *,...)
int fcntl(int, int,...)
#define Q_ASSERT_X(cond, where, what)
Definition: qglobal.h:1837
The QMutexLocker class is a convenience class that simplifies locking and unlocking mutexes...
Definition: qmutex.h:101
static int select_msecs(int nfds, fd_set *fdread, fd_set *fdwrite, int timeout)
int qt_safe_select(int nfds, fd_set *fdread, fd_set *fdwrite, fd_set *fdexcept, const struct timeval *orig_timeout)
Definition: qcore_unix.cpp:73
unsigned short ushort
Definition: qglobal.h:995
bool waitForBytesWritten(int msecs=30000)
static void qt_sa_sigchld_sigaction(int signum, siginfo_t *info, void *context)
void start(Priority=InheritPriority)
Begins execution of the thread by calling run().
HANDLE Q_PIPE
Definition: qprocess_p.h:68
int sigaction(int, const struct sigaction *, struct sigaction *)
bool waitForFinished(int msecs=30000)
int key
The QHash::iterator class provides an STL-style non-const iterator for QHash and QMultiHash.
Definition: qhash.h:330
int size() const
Returns the number of items in the list.
Definition: qlist.h:137
#define environ
void setEnabled(bool)
If enable is true, the notifier is enabled; otherwise the notifier is disabled.
static QReadWriteLock lock
Definition: proxyconf.cpp:399
static void cleanup()
Definition: qpicture.cpp:1508
if(void) toggleToolbarShown
int fetchAndAddRelaxed(int valueToAdd)
QFuture< T > run(Function function,...)
#define QT_BEGIN_INCLUDE_NAMESPACE
This macro is equivalent to QT_END_NAMESPACE.
Definition: qglobal.h:91
QProcess * process
char * qstrdup(const char *src)
Returns a duplicate string.
Definition: qbytearray.cpp:114
bool createChannel(Channel &channel)
int count(const Key &key) const
Returns the number of items associated with the key.
Definition: qhash.h:719
static QByteArray encodeName(const QString &fileName)
By default, this function converts fileName to the local 8-bit encoding determined by the user&#39;s loca...
Definition: qfile.cpp:528
bool isEmpty() const
Returns true if the byte array has size 0; otherwise returns false.
Definition: qbytearray.h:421
QStringList split(const QString &sep, SplitBehavior behavior=KeepEmptyParts, Qt::CaseSensitivity cs=Qt::CaseSensitive) const Q_REQUIRED_RESULT
Splits the string into substrings wherever sep occurs, and returns the list of those strings...
Definition: qstring.cpp:6526
static QProcessManager * processManager()
The QFileInfo class provides system-independent file information.
Definition: qfileinfo.h:60
void reserve(int size)
Attempts to allocate memory for at least size bytes.
Definition: qbytearray.h:449
void destroyPipe(Q_PIPE pipe[2])
static const KeyPair *const end
static qint64 qt_safe_write_nosignal(int fd, const void *data, qint64 len)
Definition: qcore_unix_p.h:291
void remove(QProcess *process)
#define qPrintable(string)
Definition: qglobal.h:1750
The QThread class provides a platform-independent way to manage threads.
Definition: qthread.h:59
Q_OUTOFLINE_TEMPLATE void qDeleteAll(ForwardIterator begin, ForwardIterator end)
Definition: qalgorithms.h:319
void start()
Starts this timer.
The QLatin1Char class provides an 8-bit ASCII/Latin-1 character.
Definition: qchar.h:55
static pid_t qt_safe_waitpid(pid_t pid, int *status, int options)
Definition: qcore_unix_p.h:333
#define O_WRONLY
void execChild(const char *workingDirectory, char **path, char **argv, char **envp)
The QProcess class is used to start external programs and to communicate with them.
Definition: qprocess.h:102
static qint64 qt_safe_write(int fd, const void *data, qint64 len)
Definition: qcore_unix_p.h:282
static qint64 qt_safe_read(int fd, void *data, qint64 maxlen)
Definition: qcore_unix_p.h:273
static bool equal(const QChar *a, int l, const char *b)
Definition: qurl.cpp:3270
int errno
bool endsWith(const QByteArray &a) const
Returns true if this byte array ends with byte array ba; otherwise returns false. ...
static void add_fd(int &nfds, int fd, fd_set *fdset)
#define forever
This macro is provided for convenience for writing infinite loops.
Definition: qglobal.h:2452