Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qprocess_p.h
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// Copyright (C) 2016 Intel Corporation.
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4
5#ifndef QPROCESS_P_H
6#define QPROCESS_P_H
7
8//
9// W A R N I N G
10// -------------
11//
12// This file is not part of the Qt API. It exists purely as an
13// implementation detail. This header file may change from version to
14// version without notice, or even be removed.
15//
16// We mean it.
17//
18
19#include "QtCore/qprocess.h"
20#include "QtCore/qstringlist.h"
21#include "QtCore/qhash.h"
22#include "QtCore/qmap.h"
23#include "QtCore/qshareddata.h"
24#include "QtCore/qdeadlinetimer.h"
25#include "private/qiodevice_p.h"
26
27QT_REQUIRE_CONFIG(processenvironment);
28
29#ifdef Q_OS_UNIX
30#include <QtCore/private/qorderedmutexlocker_p.h>
31#endif
32
33#ifdef Q_OS_WIN
34#include "QtCore/qt_windows.h"
35typedef HANDLE Q_PIPE;
36#define INVALID_Q_PIPE INVALID_HANDLE_VALUE
37#else
38typedef int Q_PIPE;
39#define INVALID_Q_PIPE -1
40#endif
41
43
44class QSocketNotifier;
48
49#ifdef Q_OS_WIN
50class QProcEnvKey : public QString
51{
52public:
53 QProcEnvKey() {}
54 explicit QProcEnvKey(const QString &other) : QString(other) {}
56 bool operator==(const QProcEnvKey &other) const { return !compare(other, Qt::CaseInsensitive); }
57};
58
59inline bool operator<(const QProcEnvKey &a, const QProcEnvKey &b)
60{
61 // On windows use case-insensitive ordering because that is how Windows needs the environment
62 // block sorted (https://msdn.microsoft.com/en-us/library/windows/desktop/ms682009(v=vs.85).aspx)
63 return a.compare(b, Qt::CaseInsensitive) < 0;
64}
65
67
69#else
71
73{
74public:
75 QProcEnvValue() = default;
78 bool operator==(const QProcEnvValue &other) const
79 {
80 return byteValue.isEmpty() && other.byteValue.isEmpty()
81 ? stringValue == other.stringValue
82 : bytes() == other.bytes();
83 }
85 {
88 return byteValue;
89 }
96
99};
101#endif
102
104{
105public:
108#ifdef Q_OS_WIN
109 inline Key prepareName(const QString &name) const { return Key(name); }
110 inline QString nameToString(const Key &name) const { return name; }
111 inline Value prepareValue(const QString &value) const { return value; }
112 inline QString valueToString(const Value &value) const { return value; }
113#else
114 struct NameMapMutexLocker : public QMutexLocker<QMutex>
115 {
117 };
119 {
122 : QOrderedMutexLocker(&d1->nameMapMutex, &d2->nameMapMutex)
123 {}
124 };
125
126 inline Key prepareName(const QString &name) const
127 {
128 const NameMapMutexLocker locker(this);
129 Key &ent = nameMap[name];
130 if (ent.isEmpty())
131 ent = name.toLocal8Bit();
132 return ent;
133 }
134 inline QString nameToString(const Key &name) const
135 {
136 const QString sname = QString::fromLocal8Bit(name);
137 {
138 const NameMapMutexLocker locker(this);
139 nameMap[sname] = name;
140 }
141 return sname;
142 }
143 inline Value prepareValue(const QString &value) const { return Value(value); }
144 inline QString valueToString(const Value &value) const { return value.string(); }
145
149 {
150 // We don't need to lock our own mutex, as this object is new and
151 // consequently not shared. For the same reason, non-const methods
152 // do not need a lock, as they detach objects (however, we need to
153 // ensure that they really detach before using prepareName()).
154 NameMapMutexLocker locker(&other);
155 nameMap = other.nameMap;
156 // We need to detach our nameMap, so that our mutex can protect it.
157 // As we are being detached, it likely would be detached a moment later anyway.
158 nameMap.detach();
159 }
160#endif
161
162 using Map = QMap<Key, Value>;
164
165#ifdef Q_OS_UNIX
166 typedef QHash<QString, Key> NameHash;
167 mutable NameHash nameMap;
168 mutable QMutex nameMapMutex;
169#endif
170
172 QStringList toList() const;
173 QStringList keys() const;
175};
176
177template<> Q_INLINE_TEMPLATE void QSharedDataPointer<QProcessEnvironmentPrivate>::detach()
178{
179 if (d && d->ref.loadRelaxed() == 1)
180 return;
183 x->ref.ref();
184 if (d && !d->ref.deref())
185 delete d;
186 d = x;
187}
188
189#if QT_CONFIG(process)
190
191class QProcessPrivate : public QIODevicePrivate
192{
193public:
194 Q_DECLARE_PUBLIC(QProcess)
195
196 struct Channel {
197 enum ProcessChannelType : char {
198 Normal = 0,
199 PipeSource = 1,
200 PipeSink = 2,
201 Redirect = 3
202 };
203
204 void clear();
205
206 Channel &operator=(const QString &fileName)
207 {
208 clear();
209 file = fileName;
210 type = fileName.isEmpty() ? Normal : Redirect;
211 return *this;
212 }
213
214 void pipeTo(QProcessPrivate *other)
215 {
216 clear();
217 process = other;
218 type = PipeSource;
219 }
220
221 void pipeFrom(QProcessPrivate *other)
222 {
223 clear();
224 process = other;
225 type = PipeSink;
226 }
227
229 QProcessPrivate *process = nullptr;
230#ifdef Q_OS_UNIX
231 QSocketNotifier *notifier = nullptr;
232#else
233 union {
234 QWindowsPipeReader *reader = nullptr;
235 QWindowsPipeWriter *writer;
236 };
237#endif
239
240 ProcessChannelType type = Normal;
241 bool closed = false;
242 bool append = false;
243 };
244
245 QProcessPrivate();
246 virtual ~QProcessPrivate();
247
248 // private slots
249 bool _q_canReadStandardOutput();
250 bool _q_canReadStandardError();
251#ifdef Q_OS_WIN
252 qint64 pipeWriterBytesToWrite() const;
253 void _q_bytesWritten(qint64 bytes);
254 void _q_writeFailed();
255#else
256 bool _q_canWrite();
257 bool writeToStdin();
258#endif
259 bool _q_startupNotification();
260 void _q_processDied();
261
262 Channel stdinChannel;
263 Channel stdoutChannel;
264 Channel stderrChannel;
265 bool openChannels();
266 bool openChannelsForDetached();
267 bool openChannel(Channel &channel);
268 void closeChannel(Channel *channel);
269 void closeWriteChannel();
270 void closeChannels();
271 bool tryReadFromChannel(Channel *channel); // obviously, only stdout and stderr
272
275 QString workingDirectory;
277#if defined(Q_OS_WIN)
278 QString nativeArguments;
279 QProcess::CreateProcessArgumentModifier modifyCreateProcessArgs;
280 QWinEventNotifier *processFinishedNotifier = nullptr;
281 Q_PROCESS_INFORMATION *pid = nullptr;
282#else
283 struct UnixExtras {
284 std::function<void(void)> childProcessModifier;
285 QProcess::UnixProcessParameters processParameters;
286 };
287 std::unique_ptr<UnixExtras> unixExtras;
288 QSocketNotifier *stateNotifier = nullptr;
289 Q_PIPE childStartedPipe[2] = {INVALID_Q_PIPE, INVALID_Q_PIPE};
290 pid_t pid = 0;
291 int forkfd = -1;
292#endif
293
294 int exitCode = 0;
295 quint8 processState = QProcess::NotRunning;
296 quint8 exitStatus = QProcess::NormalExit;
297 quint8 processError = QProcess::UnknownError;
298 quint8 processChannelMode = QProcess::SeparateChannels;
299 quint8 inputChannelMode = QProcess::ManagedInputChannel;
300 bool emittedReadyRead = false;
301 bool emittedBytesWritten = false;
302
303 void start(QIODevice::OpenMode mode);
304 void startProcess();
305#if defined(Q_OS_UNIX)
306 void commitChannels() const;
307#endif
308 bool processStarted(QString *errorMessage = nullptr);
309 void processFinished();
310 void terminateProcess();
311 void killProcess();
312#ifdef Q_OS_UNIX
313 void waitForDeadChild();
314#else
315 void findExitCode();
316#endif
317#ifdef Q_OS_WIN
318 STARTUPINFOW createStartupInfo();
319 bool callCreateProcess(QProcess::CreateProcessArguments *cpargs);
320 bool drainOutputPipes();
321#endif
322
323 bool startDetached(qint64 *pPid);
324
325 bool waitForStarted(const QDeadlineTimer &deadline);
327 bool waitForBytesWritten(const QDeadlineTimer &deadline);
329
330 qint64 bytesAvailableInChannel(const Channel *channel) const;
331 qint64 readFromChannel(const Channel *channel, char *data, qint64 maxlen);
332
333 void destroyPipe(Q_PIPE pipe[2]);
334 void cleanup();
335 void setError(QProcess::ProcessError error, const QString &description = QString());
336 void setErrorAndEmit(QProcess::ProcessError error, const QString &description = QString());
337
338 const QProcessEnvironmentPrivate *environmentPrivate() const
339 { return environment.d.constData(); }
340};
341
342#endif // QT_CONFIG(process)
343
345
346#endif // QPROCESS_P_H
DarwinBluetooth::LECBManagerNotifier * notifier
IOBluetoothL2CAPChannel * channel
bool ref() noexcept
\inmodule QtCore
Definition qbytearray.h:57
bool isEmpty() const noexcept
Returns true if the byte array has size 0; otherwise returns false.
Definition qbytearray.h:107
\inmodule QtCore
\inmodule QtCore
Definition qmutex.h:313
\inmodule QtCore
Definition qmutex.h:281
QByteArray byteValue
Definition qprocess_p.h:97
QProcEnvValue(const QString &value)
Definition qprocess_p.h:76
bool operator==(const QProcEnvValue &other) const
Definition qprocess_p.h:78
QByteArray bytes() const
Definition qprocess_p.h:84
QProcEnvValue()=default
QString stringValue
Definition qprocess_p.h:98
QProcEnvValue(const QByteArray &value)
Definition qprocess_p.h:77
QString string() const
Definition qprocess_p.h:90
QProcessEnvironmentPrivate(const QProcessEnvironmentPrivate &other)
Definition qprocess_p.h:147
Value prepareValue(const QString &value) const
Definition qprocess_p.h:143
static QProcessEnvironment fromList(const QStringList &list)
Definition qprocess.cpp:71
Key prepareName(const QString &name) const
Definition qprocess_p.h:126
QString valueToString(const Value &value) const
Definition qprocess_p.h:144
void insert(const QProcessEnvironmentPrivate &other)
Definition qprocess.cpp:100
QString nameToString(const Key &name) const
Definition qprocess_p.h:134
QStringList keys() const
Definition qprocess.cpp:89
QStringList toList() const
Definition qprocess.cpp:62
\inmodule QtCore
Definition qprocess.h:32
void detach()
If the shared data object's reference count is greater than 1, this function creates a deep copy of t...
Definition qshareddata.h:40
const T * constData() const noexcept
Returns a const pointer to the shared data object.
Definition qshareddata.h:51
\inmodule QtCore
Definition qshareddata.h:19
QAtomicInt ref
Definition qshareddata.h:21
\inmodule QtCore
\inmodule QtCore
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
static QString fromLocal8Bit(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5949
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:192
QByteArray toLocal8Bit() const &
Definition qstring.h:638
\inmodule QtCore
b clear()
list append(new Employee("Blackpool", "Stephen"))
QList< QVariant > arguments
Combined button and popup list for selecting options.
@ CaseInsensitive
QImageReader reader("image.png")
[1]
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char return DBusMessage return DBusMessage const char return DBusMessage dbus_bool_t return DBusMessage dbus_uint32_t return DBusMessage void
DBusConnection const char DBusError * error
typedef QByteArray(EGLAPIENTRYP PFNQGSGETDISPLAYSPROC)()
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
GLboolean GLboolean GLboolean b
GLint GLint GLint GLint GLint x
[0]
GLenum mode
GLboolean GLboolean GLboolean GLboolean a
[7]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum type
GLuint program
GLuint start
GLuint name
int Q_PIPE
Definition qprocess_p.h:38
QByteArray QProcEnvKey
Definition qprocess_p.h:70
#define INVALID_Q_PIPE
Definition qprocess_p.h:39
static void setError(QJsonObject *response, const QString &msg)
bool operator==(const QRandomGenerator &rng1, const QRandomGenerator &rng2)
Definition qrandom.cpp:1220
static bool operator<(const QSettingsIniKey &k1, const QSettingsIniKey &k2)
void startProcess()
Definition main.cpp:6
#define QT_REQUIRE_CONFIG(feature)
static int compare(quint64 a, quint64 b)
@ Q_RELOCATABLE_TYPE
Definition qtypeinfo.h:158
#define Q_DECLARE_TYPEINFO(TYPE, FLAGS)
Definition qtypeinfo.h:180
long long qint64
Definition qtypes.h:60
unsigned char quint8
Definition qtypes.h:46
static QString errorMessage(QUrlPrivate::ErrorCode errorCode, const QString &errorSource, qsizetype errorPosition)
Definition qurl.cpp:3517
QList< int > list
[14]
future waitForFinished()
QFile file
[0]
device waitForReadyRead(deadline)
QDeadlineTimer deadline(30s)
QDate d1(1995, 5, 17)
[0]
QDate d2(1995, 5, 20)
QSharedPointer< T > other(t)
[5]
NameMapMutexLocker(const QProcessEnvironmentPrivate *d)
Definition qprocess_p.h:116
OrderedNameMapMutexLocker(const QProcessEnvironmentPrivate *d1, const QProcessEnvironmentPrivate *d2)
Definition qprocess_p.h:120