20#include "QtCore/qprocess.h"
21#include "QtCore/qstringlist.h"
22#include "QtCore/qhash.h"
23#include "QtCore/qmap.h"
24#include "QtCore/qshareddata.h"
25#include "QtCore/qdeadlinetimer.h"
26#include "private/qiodevice_p.h"
31#include <QtCore/private/qorderedmutexlocker_p.h>
35#include "QtCore/qt_windows.h"
37#define INVALID_Q_PIPE INVALID_HANDLE_VALUE
40#define INVALID_Q_PIPE -1
46class QWindowsPipeReader;
47class QWindowsPipeWriter;
48class QWinEventNotifier;
51class QProcEnvKey :
public QString
55 explicit QProcEnvKey(
const QString &other) : QString(other) {}
56 QProcEnvKey(
const QProcEnvKey &other) : QString(other) {}
57 bool operator==(
const QProcEnvKey &other)
const {
return !compare(other, Qt::CaseInsensitive); }
60inline bool operator<(
const QProcEnvKey &a,
const QProcEnvKey &b)
64 return a.compare(b, Qt::CaseInsensitive) < 0;
67Q_DECLARE_TYPEINFO(QProcEnvKey, Q_RELOCATABLE_TYPE);
69typedef QString QProcEnvValue;
71using QProcEnvKey = QByteArray;
81 return byteValue.isEmpty() && other.byteValue.isEmpty()
82 ? stringValue == other.stringValue
83 : bytes() == other.bytes();
87 if (byteValue.isEmpty() && !stringValue.isEmpty())
88 byteValue = stringValue.toLocal8Bit();
93 if (stringValue.isEmpty() && !byteValue.isEmpty())
94 stringValue = QString::fromLocal8Bit(byteValue);
124 Key &ent = nameMap[name];
126 ent = name.toLocal8Bit();
131 const QString sname = QString::fromLocal8Bit(name);
132 nameMap[sname] = name;
162 nameMap = other.nameMap;
186template<> Q_INLINE_TEMPLATE
void QSharedDataPointer<QProcessEnvironmentPrivate>::detach()
188 if (d && d->ref.loadRelaxed() == 1)
190 QProcessEnvironmentPrivate *x = (d ?
new QProcessEnvironmentPrivate(*d)
191 :
new QProcessEnvironmentPrivate);
193 if (d && !d->ref.deref())
198#if QT_CONFIG(process)
200class QProcessPrivate :
public QIODevicePrivate
203 Q_DECLARE_PUBLIC(QProcess)
206 enum ProcessChannelType :
char {
215 Channel &operator=(
const QString &fileName)
219 type = fileName.isEmpty() ? Normal : Redirect;
223 void pipeTo(QProcessPrivate *other)
230 void pipeFrom(QProcessPrivate *other)
238 QProcessPrivate *process =
nullptr;
240 QSocketNotifier *notifier =
nullptr;
243 QWindowsPipeReader *reader =
nullptr;
244 QWindowsPipeWriter *writer;
247 Q_PIPE pipe[2] = {INVALID_Q_PIPE, INVALID_Q_PIPE};
249 ProcessChannelType type = Normal;
255 virtual ~QProcessPrivate();
258 bool _q_canReadStandardOutput();
259 bool _q_canReadStandardError();
261 qint64 pipeWriterBytesToWrite()
const;
262 void _q_bytesWritten(qint64 bytes);
263 void _q_writeFailed();
268 bool _q_startupNotification();
269 void _q_processDied();
271 Channel stdinChannel;
272 Channel stdoutChannel;
273 Channel stderrChannel;
275 bool openChannelsForDetached();
276 bool openChannel(Channel &channel);
277 void closeChannel(Channel *channel);
278 void closeWriteChannel();
279 void closeChannels();
280 bool tryReadFromChannel(Channel *channel);
283 QStringList arguments;
284 QString workingDirectory;
285 QProcessEnvironment environment = QProcessEnvironment::InheritFromParent;
287 QString nativeArguments;
288 QProcess::CreateProcessArgumentModifier modifyCreateProcessArgs;
289 QWinEventNotifier *processFinishedNotifier =
nullptr;
290 Q_PROCESS_INFORMATION *pid =
nullptr;
293 std::function<
void(
void)> childProcessModifier;
294 QProcess::UnixProcessParameters processParameters;
296 std::unique_ptr<UnixExtras> unixExtras;
297 QSocketNotifier *stateNotifier =
nullptr;
298 Q_PIPE childStartedPipe[2] = {INVALID_Q_PIPE, INVALID_Q_PIPE};
304 quint8 processState = QProcess::NotRunning;
305 quint8 exitStatus = QProcess::NormalExit;
306 quint8 processError = QProcess::UnknownError;
307 quint8 processChannelMode = QProcess::SeparateChannels;
308 quint8 inputChannelMode = QProcess::ManagedInputChannel;
309 bool emittedReadyRead =
false;
310 bool emittedBytesWritten =
false;
312 void start(QIODevice::OpenMode mode);
314#if defined(Q_OS_UNIX)
315 void commitChannels()
const;
317 bool processStarted(QString *errorMessage =
nullptr);
318 void processFinished();
319 void terminateProcess();
322 void waitForDeadChild();
327 STARTUPINFOW createStartupInfo();
328 bool callCreateProcess(QProcess::CreateProcessArguments *cpargs);
329 bool drainOutputPipes();
332 bool startDetached(qint64 *pPid);
334 bool waitForStarted(
const QDeadlineTimer &deadline);
335 bool waitForReadyRead(
const QDeadlineTimer &deadline);
336 bool waitForBytesWritten(
const QDeadlineTimer &deadline);
337 bool waitForFinished(
const QDeadlineTimer &deadline);
339 qint64 bytesAvailableInChannel(
const Channel *channel)
const;
340 qint64 readFromChannel(
const Channel *channel,
char *data, qint64 maxlen);
342 void destroyPipe(Q_PIPE pipe[2]);
344 void setError(QProcess::ProcessError error,
const QString &description = QString());
345 void setErrorAndEmit(QProcess::ProcessError error,
const QString &description = QString());
347 const QProcessEnvironmentPrivate *environmentPrivate()
const
348 {
return environment.d.constData(); }
QProcEnvValue(const QString &value)
bool operator==(const QProcEnvValue &other) const
QProcessEnvironmentPrivate(const QProcessEnvironmentPrivate &other)
Value prepareValue(const QString &value) const
QProcessEnvironmentPrivate()
static QProcessEnvironment fromList(const QStringList &list)
Key prepareName(const QString &name) const
QString valueToString(const Value &value) const
void insert(const QProcessEnvironmentPrivate &other)
QString nameToString(const Key &name) const
QStringList toList() const
Combined button and popup list for selecting options.
QT_REQUIRE_CONFIG(animation)
bool comparesEqual(const QFileInfo &lhs, const QFileInfo &rhs)
QT_REQUIRE_CONFIG(processenvironment)
Q_DECLARE_TYPEINFO(QProcEnvValue, Q_RELOCATABLE_TYPE)
MutexLocker(const QProcessEnvironmentPrivate *d)
OrderedMutexLocker(const QProcessEnvironmentPrivate *d1, const QProcessEnvironmentPrivate *d2)