Qt 4.8
qprocess_p.h
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 #ifndef QPROCESS_P_H
43 #define QPROCESS_P_H
44 
45 //
46 // W A R N I N G
47 // -------------
48 //
49 // This file is not part of the Qt API. It exists purely as an
50 // implementation detail. This header file may change from version to
51 // version without notice, or even be removed.
52 //
53 // We mean it.
54 //
55 
56 #include "QtCore/qprocess.h"
57 #include "QtCore/qstringlist.h"
58 #include "QtCore/qhash.h"
59 #include "QtCore/qshareddata.h"
60 #include "private/qringbuffer_p.h"
61 #include "private/qiodevice_p.h"
62 #ifdef Q_OS_UNIX
63 #include <QtCore/private/qorderedmutexlocker_p.h>
64 #endif
65 
66 #ifdef Q_OS_WIN
67 #include "QtCore/qt_windows.h"
68 typedef HANDLE Q_PIPE;
69 #define INVALID_Q_PIPE INVALID_HANDLE_VALUE
70 #else
71 typedef int Q_PIPE;
72 #define INVALID_Q_PIPE -1
73 #endif
74 
75 #ifndef QT_NO_PROCESS
76 
78 
79 class QSocketNotifier;
80 class QWindowsPipeWriter;
81 class QWinEventNotifier;
82 class QTimer;
83 #if defined(Q_OS_SYMBIAN)
84 class RProcess;
85 #endif
86 
87 #ifdef Q_OS_WIN
88 class QProcEnvKey : public QString
89 {
90 public:
92  explicit QProcEnvKey(const QString &other) : QString(other) {}
93  QProcEnvKey(const QProcEnvKey &other) : QString(other) {}
94  bool operator==(const QProcEnvKey &other) const { return !compare(other, Qt::CaseInsensitive); }
95 };
96 inline uint qHash(const QProcEnvKey &key) { return qHash(key.toCaseFolded()); }
97 
99 #else
100 class QProcEnvKey
101 {
102 public:
103  QProcEnvKey() : hash(0) {}
104  explicit QProcEnvKey(const QByteArray &other) : key(other), hash(qHash(key)) {}
105  QProcEnvKey(const QProcEnvKey &other) { *this = other; }
106  bool operator==(const QProcEnvKey &other) const { return key == other.key; }
107 
108  QByteArray key;
109  uint hash;
110 };
111 inline uint qHash(const QProcEnvKey &key) { return key.hash; }
112 
113 class QProcEnvValue
114 {
115 public:
116  QProcEnvValue() {}
117  QProcEnvValue(const QProcEnvValue &other) { *this = other; }
118  explicit QProcEnvValue(const QString &value) : stringValue(value) {}
119  explicit QProcEnvValue(const QByteArray &value) : byteValue(value) {}
120  bool operator==(const QProcEnvValue &other) const
121  {
122  return byteValue.isEmpty() && other.byteValue.isEmpty()
123  ? stringValue == other.stringValue
124  : bytes() == other.bytes();
125  }
126  QByteArray bytes() const
127  {
128  if (byteValue.isEmpty() && !stringValue.isEmpty())
129  byteValue = stringValue.toLocal8Bit();
130  return byteValue;
131  }
132  QString string() const
133  {
134  if (stringValue.isEmpty() && !byteValue.isEmpty())
135  stringValue = QString::fromLocal8Bit(byteValue);
136  return stringValue;
137  }
138 
139  mutable QByteArray byteValue;
140  mutable QString stringValue;
141 };
143 #endif
145 
147 {
148 public:
149  typedef QProcEnvKey Key;
151 #ifdef Q_OS_WIN
152  inline Key prepareName(const QString &name) const { return Key(name); }
153  inline QString nameToString(const Key &name) const { return name; }
154  inline Value prepareValue(const QString &value) const { return value; }
155  inline QString valueToString(const Value &value) const { return value; }
156  struct MutexLocker {
158  };
161  const QProcessEnvironmentPrivate *) {}
162  };
163 #else
164  inline Key prepareName(const QString &name) const
165  {
166  Key &ent = nameMap[name];
167  if (ent.key.isEmpty())
168  ent = Key(name.toLocal8Bit());
169  return ent;
170  }
171  inline QString nameToString(const Key &name) const
172  {
173  const QString sname = QString::fromLocal8Bit(name.key);
174  nameMap[sname] = name;
175  return sname;
176  }
177  inline Value prepareValue(const QString &value) const { return Value(value); }
178  inline QString valueToString(const Value &value) const { return value.string(); }
179 
180  struct MutexLocker : public QMutexLocker
181  {
183  };
185  {
187  const QProcessEnvironmentPrivate *d2) :
188  QOrderedMutexLocker(&d1->mutex, &d2->mutex)
189  {}
190  };
191 
194  QSharedData()
195  {
196  // This being locked ensures that the functions that only assign
197  // d pointers don't need explicit locking.
198  // We don't need to lock our own mutex, as this object is new and
199  // consequently not shared. For the same reason, non-const methods
200  // do not need a lock, as they detach objects (however, we need to
201  // ensure that they really detach before using prepareName()).
202  MutexLocker locker(&other);
203  hash = other.hash;
204  nameMap = other.nameMap;
205  // We need to detach our members, so that our mutex can protect them.
206  // As we are being detached, they likely would be detached a moment later anyway.
207  hash.detach();
208  nameMap.detach();
209  }
210 #endif
211 
213  Hash hash;
214 
215 #ifdef Q_OS_UNIX
217  mutable NameHash nameMap;
218 
219  mutable QMutex mutex;
220 #endif
221 
222  static QProcessEnvironment fromList(const QStringList &list);
223  QStringList toList() const;
224  QStringList keys() const;
225  void insert(const QProcessEnvironmentPrivate &other);
226 };
227 
229 {
230  if (d && d->ref == 1)
231  return;
233  : new QProcessEnvironmentPrivate);
234  x->ref.ref();
235  if (d && !d->ref.deref())
236  delete d;
237  d = x;
238 }
239 
241 {
242 public:
244 
245  struct Channel {
247  Normal = 0,
248  PipeSource = 1,
249  PipeSink = 2,
250  Redirect = 3
251  // if you add "= 4" here, increase the number of bits below
252  };
253 
254  Channel() : process(0), notifier(0), type(Normal), closed(false), append(false)
255  {
256  pipe[0] = INVALID_Q_PIPE;
257  pipe[1] = INVALID_Q_PIPE;
258  }
259 
260  void clear();
261 
262  Channel &operator=(const QString &fileName)
263  {
264  clear();
265  file = fileName;
266  type = fileName.isEmpty() ? Normal : Redirect;
267  return *this;
268  }
269 
270  void pipeTo(QProcessPrivate *other)
271  {
272  clear();
273  process = other;
274  type = PipeSource;
275  }
276 
278  {
279  clear();
280  process = other;
281  type = PipeSink;
282  }
283 
287  Q_PIPE pipe[2];
288 
289  unsigned type : 2;
290  bool closed : 1;
291  bool append : 1;
292  };
293 
294  QProcessPrivate();
295  virtual ~QProcessPrivate();
296 
297  // private slots
298  bool _q_canReadStandardOutput();
299  bool _q_canReadStandardError();
300  bool _q_canWrite();
301  bool _q_startupNotification();
302  bool _q_processDied();
303  void _q_notified();
304 
312 
313  bool dying;
316 
320  bool createChannel(Channel &channel);
321  void closeWriteChannel();
322 
325 #if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN)
327 #endif
329 
333 
334  Q_PIPE childStartedPipe[2];
335  Q_PIPE deathPipe[2];
336  void destroyPipe(Q_PIPE pipe[2]);
337 
340 
341  // the wonderful windows notifier
345 
346  void startProcess();
347 #if defined(Q_OS_UNIX) && !defined(Q_OS_SYMBIAN) && !defined(Q_OS_QNX)
348  void execChild(const char *workingDirectory, char **path, char **argv, char **envp);
349 #elif defined(Q_OS_QNX)
350  pid_t spawnChild(const char *workingDirectory, char **argv, char **envp);
351 #endif
352  bool processStarted();
353  void terminateProcess();
354  void killProcess();
355  void findExitCode();
356 #ifdef Q_OS_UNIX
357  bool waitForDeadChild();
358 #endif
359 #ifdef Q_OS_WIN
360  void flushPipeWriter();
361  qint64 pipeWriterBytesToWrite() const;
362 #endif
363 
364  static bool startDetached(const QString &program, const QStringList &arguments, const QString &workingDirectory = QString(),
365  qint64 *pid = 0);
366 
367  int exitCode;
369  bool crashed;
370 #ifdef Q_OS_UNIX
371  int serial;
372 #endif
373 
374  bool waitForStarted(int msecs = 30000);
375  bool waitForReadyRead(int msecs = 30000);
376  bool waitForBytesWritten(int msecs = 30000);
377  bool waitForFinished(int msecs = 30000);
378  bool waitForWrite(int msecs = 30000);
379 
380  qint64 bytesAvailableFromStdout() const;
381  qint64 bytesAvailableFromStderr() const;
382  qint64 readFromStdout(char *data, qint64 maxlen);
383  qint64 readFromStderr(char *data, qint64 maxlen);
384  qint64 writeToStdin(const char *data, qint64 maxlen);
385 
386  void cleanup();
387 #ifdef Q_OS_UNIX
388  static void initializeProcessManager();
389 #endif
390 
391 #ifdef Q_OS_SYMBIAN
392  bool processLaunched;
393  RProcess* symbianProcess;
394 #endif
395 };
396 
398 
399 #endif // QT_NO_PROCESS
400 
401 #endif // QPROCESS_P_H
The QProcessEnvironment class holds the environment variables that can be passed to a program...
Definition: qprocess.h:68
QAtomicInt ref
Definition: qshareddata.h:59
static uint hash(const uchar *p, int n)
Definition: qhash.cpp:68
uint qHash(const QProcEnvKey &key)
Definition: qprocess_p.h:96
QProcEnvKey(const QString &other)
Definition: qprocess_p.h:92
OrderedMutexLocker(const QProcessEnvironmentPrivate *, const QProcessEnvironmentPrivate *)
Definition: qprocess_p.h:160
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
int type
Definition: qmetatype.cpp:239
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
The QMutex class provides access serialization between threads.
Definition: qmutex.h:60
ProcessError
This enum describes the different types of errors that are reported by QProcess.
Definition: qprocess.h:106
ProcessChannel
This enum describes the process channels used by the running process.
Definition: qprocess.h:119
QProcEnvKey(const QProcEnvKey &other)
Definition: qprocess_p.h:93
void pipeFrom(QProcessPrivate *other)
Definition: qprocess_p.h:277
void pipeTo(QProcessPrivate *other)
Definition: qprocess_p.h:270
void detach()
If the shared data object&#39;s reference count is greater than 1, this function creates a deep copy of t...
Definition: qshareddata.h:75
bool emittedBytesWritten
Definition: qprocess_p.h:315
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:135
Value prepareValue(const QString &value) const
Definition: qprocess_p.h:154
QProcess::ProcessState processState
Definition: qprocess_p.h:308
Channel stdinChannel
Definition: qprocess_p.h:317
ProcessState
This enum describes the different states of QProcess.
Definition: qprocess.h:114
QString QProcEnvValue
Definition: qprocess_p.h:98
QString nameToString(const Key &name) const
Definition: qprocess_p.h:153
QString nativeArguments
Definition: qprocess_p.h:326
bool ref()
Atomically increments the value of this QAtomicInt.
Key prepareName(const QString &name) const
Definition: qprocess_p.h:152
The QString class provides a Unicode character string.
Definition: qstring.h:83
QProcessEnvironment environment
Definition: qprocess_p.h:328
static QList< QVariant > toList(char **buf, int count, T *=0)
Definition: qsql_ibase.cpp:472
QString valueToString(const Value &value) const
Definition: qprocess_p.h:155
#define INVALID_Q_PIPE
Definition: qprocess_p.h:69
QChar * data()
Returns a pointer to the data stored in the QString.
Definition: qstring.h:710
QStringList keys
QBasicAtomicInt ref
Definition: qstring.h:604
QSocketNotifier * notifier
Definition: qprocess_p.h:286
The QSocketNotifier class provides support for monitoring activity on a file descriptor.
QProcess::ProcessChannel processChannel
Definition: qprocess_p.h:305
QStringList arguments
Definition: qprocess_p.h:324
QWindowsPipeWriter * pipeWriter
Definition: qprocess_p.h:343
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
QProcess::ProcessError processError
Definition: qprocess_p.h:307
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition: qstring.h:704
ProcessChannelMode
This enum describes the process channel modes of QProcess.
Definition: qprocess.h:123
const char * name
Channel stdoutChannel
Definition: qprocess_p.h:318
QHash< QString, Key > NameHash
Definition: qprocess_p.h:216
The QStringList class provides a list of strings.
Definition: qstringlist.h:66
bool emittedReadyRead
Definition: qprocess_p.h:314
QString toCaseFolded() const Q_REQUIRED_RESULT
Returns the case folded equivalent of the string.
Definition: qstring.cpp:5441
#define Q_INLINE_TEMPLATE
Definition: qglobal.h:1713
unsigned int uint
Definition: qglobal.h:996
Q_DECLARE_TYPEINFO(QProcEnvKey, Q_MOVABLE_TYPE)
QProcess::ProcessChannelMode processChannelMode
Definition: qprocess_p.h:306
__int64 qint64
Definition: qglobal.h:942
void * HANDLE
Definition: qnamespace.h:1671
QByteArray toLocal8Bit() const Q_REQUIRED_RESULT
Returns the local 8-bit representation of the string as a QByteArray.
Definition: qstring.cpp:4049
Data * d
Definition: qstring.h:618
QProcessPrivate * process
Definition: qprocess_p.h:285
qint64 Q_PID
Definition: qprocess.h:58
ExitStatus
This enum describes the different exit statuses of QProcess.
Definition: qprocess.h:128
The QMutexLocker class is a convenience class that simplifies locking and unlocking mutexes...
Definition: qmutex.h:101
#define Q_DECLARE_PUBLIC(Class)
Definition: qglobal.h:2477
QString & append(QChar c)
Definition: qstring.cpp:1777
int compare(const QString &s) const
Definition: qstring.cpp:5037
QProcess::ExitStatus exitStatus
Definition: qprocess_p.h:368
The QSharedData class is a base class for shared data objects.
Definition: qshareddata.h:56
void clear()
Clears the contents of the string and makes it empty.
Definition: qstring.h:723
Channel stderrChannel
Definition: qprocess_p.h:319
HANDLE Q_PIPE
Definition: qprocess_p.h:68
QString workingDirectory
Definition: qprocess_p.h:309
int key
MutexLocker(const QProcessEnvironmentPrivate *)
Definition: qprocess_p.h:157
QSocketNotifier * startupSocketNotifier
Definition: qprocess_p.h:338
static void cleanup()
Definition: qpicture.cpp:1508
bool operator==(const QProcEnvKey &other) const
Definition: qprocess_p.h:94
QRingBuffer errorReadBuffer
Definition: qprocess_p.h:331
QWinEventNotifier * processFinishedNotifier
Definition: qprocess_p.h:344
The QTimer class provides repetitive and single-shot timers.
Definition: qtimer.h:56
QSocketNotifier * deathNotifier
Definition: qprocess_p.h:339
QHash< Key, Value > Hash
Definition: qprocess_p.h:212
QString program
Definition: qprocess_p.h:323
QRingBuffer writeBuffer
Definition: qprocess_p.h:332
QString & insert(int i, QChar c)
Definition: qstring.cpp:1671
static QString fileName(const QString &fileUrl)
Channel & operator=(const QString &fileName)
Definition: qprocess_p.h:262
QRingBuffer outputReadBuffer
Definition: qprocess_p.h:330
The QProcess class is used to start external programs and to communicate with them.
Definition: qprocess.h:102
QTimer * notifier
Definition: qprocess_p.h:342
QString()
Constructs a null string.
Definition: qstring.h:879