QtcProcess: Delay calls to newProcessInstance()

I'd really like to keep/re-enable at least the terminal use
as kind of property not directly tied to the QtcProcess object
life time.

This here is a first step towards this goal (and only a sketch)

I am not sure whether I like using a pointer to a "parent"
data struct as a means to propagate data, but it works, and
it's easy to add a new data item without touching all lower levels.

Change-Id: Ice2d3246951438a14383b097f307fd61306c29db
Reviewed-by: Jarek Kobus <jaroslaw.kobus@qt.io>
This commit is contained in:
hjk
2022-02-10 18:09:42 +01:00
parent bdd7fcbac2
commit 825c89987c

View File

@@ -212,9 +212,23 @@ public:
bool keepRawData = true; bool keepRawData = true;
}; };
class ProcessSetupData
{
public:
QString m_nativeArguments;
QString m_standardInputFile;
QString m_initialErrorString;
bool m_belowNormalPriority = false;
bool m_lowPriority = false;
bool m_unixTerminalDisabled = false;
bool m_abortOnMetaChars = true;
QProcess::ProcessChannelMode m_procesChannelMode = QProcess::SeparateChannels;
};
class ProcessInterface : public QObject class ProcessInterface : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
ProcessInterface(QObject *parent, ProcessMode processMode) ProcessInterface(QObject *parent, ProcessMode processMode)
: QObject(parent) : QObject(parent)
@@ -235,9 +249,6 @@ public:
virtual void close() = 0; virtual void close() = 0;
virtual qint64 write(const QByteArray &data) = 0; virtual qint64 write(const QByteArray &data) = 0;
virtual void setStandardInputFile(const QString &fileName) = 0;
virtual void setProcessChannelMode(QProcess::ProcessChannelMode mode) = 0;
virtual QString program() const = 0; virtual QString program() const = 0;
virtual QProcess::ProcessError error() const = 0; virtual QProcess::ProcessError error() const = 0;
virtual QProcess::ProcessState state() const = 0; virtual QProcess::ProcessState state() const = 0;
@@ -255,18 +266,8 @@ public:
virtual void interruptProcess() { QTC_CHECK(false); } virtual void interruptProcess() { QTC_CHECK(false); }
virtual qint64 applicationMainThreadID() const { QTC_CHECK(false); return -1; } virtual qint64 applicationMainThreadID() const { QTC_CHECK(false); return -1; }
void setLowPriority() { m_lowPriority = true; } const ProcessMode m_processMode;
bool isLowPriority() const { return m_lowPriority; } ProcessSetupData *m_setup = nullptr;
void setUnixTerminalDisabled() { m_unixTerminalDisabled = true; }
bool isUnixTerminalDisabled() const { return m_unixTerminalDisabled; }
void setAbortOnMetaChars(bool abort) { m_abortOnMetaChars = abort; }
bool isAbortOnMetaChars() const { return m_abortOnMetaChars; }
void setBelowNormalPriority() { m_belowNormalPriority = true; }
bool isBelowNormalPriority() const { return m_belowNormalPriority; }
void setNativeArguments(const QString &arguments) { m_nativeArguments = arguments; }
QString nativeArguments() const { return m_nativeArguments; }
signals: signals:
void started(); void started();
@@ -274,16 +275,6 @@ signals:
void errorOccurred(QProcess::ProcessError error); void errorOccurred(QProcess::ProcessError error);
void readyReadStandardOutput(); void readyReadStandardOutput();
void readyReadStandardError(); void readyReadStandardError();
protected:
ProcessMode processMode() const { return m_processMode; }
private:
const ProcessMode m_processMode;
bool m_belowNormalPriority = false;
QString m_nativeArguments;
bool m_lowPriority = false;
bool m_unixTerminalDisabled = false;
bool m_abortOnMetaChars = true;
}; };
class TerminalImpl : public ProcessInterface class TerminalImpl : public ProcessInterface
@@ -315,7 +306,7 @@ public:
void customStart(const CommandLine &command, const FilePath &workingDirectory, void customStart(const CommandLine &command, const FilePath &workingDirectory,
const Environment &environment) override const Environment &environment) override
{ {
m_terminal.setAbortOnMetaChars(isAbortOnMetaChars()); m_terminal.setAbortOnMetaChars(m_setup->m_abortOnMetaChars);
m_terminal.setCommand(command); m_terminal.setCommand(command);
m_terminal.setWorkingDirectory(workingDirectory); m_terminal.setWorkingDirectory(workingDirectory);
m_terminal.setEnvironment(environment); m_terminal.setEnvironment(environment);
@@ -327,10 +318,6 @@ public:
void close() override { m_terminal.stopProcess(); } void close() override { m_terminal.stopProcess(); }
qint64 write(const QByteArray &) override { QTC_CHECK(false); return -1; } qint64 write(const QByteArray &) override { QTC_CHECK(false); return -1; }
void setStandardInputFile(const QString &fileName) override { Q_UNUSED(fileName) QTC_CHECK(false); }
// intentionally no-op without an assert
void setProcessChannelMode(QProcess::ProcessChannelMode mode) override { Q_UNUSED(mode) }
QString program() const override { QTC_CHECK(false); return {}; } QString program() const override { QTC_CHECK(false); return {}; }
QProcess::ProcessError error() const override { return m_terminal.error(); } QProcess::ProcessError error() const override { return m_terminal.error(); }
QProcess::ProcessState state() const override { return m_terminal.state(); } QProcess::ProcessState state() const override { return m_terminal.state(); }
@@ -384,21 +371,26 @@ public:
{ m_process->setProcessEnvironment(environment); } { m_process->setProcessEnvironment(environment); }
void setWorkingDirectory(const QString &dir) override void setWorkingDirectory(const QString &dir) override
{ m_process->setWorkingDirectory(dir); } { m_process->setWorkingDirectory(dir); }
void start(const QString &program, const QStringList &arguments, const QByteArray &writeData) override void start(const QString &program, const QStringList &arguments, const QByteArray &writeData) override
{ {
ProcessStartHandler *handler = m_process->processStartHandler(); ProcessStartHandler *handler = m_process->processStartHandler();
handler->setProcessMode(processMode()); handler->setProcessMode(m_processMode);
handler->setWriteData(writeData); handler->setWriteData(writeData);
if (isBelowNormalPriority()) if (m_setup->m_belowNormalPriority)
handler->setBelowNormalPriority(); handler->setBelowNormalPriority();
handler->setNativeArguments(nativeArguments()); handler->setNativeArguments(m_setup->m_nativeArguments);
if (isLowPriority()) m_process->setStandardInputFile(m_setup->m_standardInputFile);
m_process->setProcessChannelMode(m_setup->m_procesChannelMode);
m_process->setErrorString(m_setup->m_initialErrorString);
if (m_setup->m_lowPriority)
m_process->setLowPriority(); m_process->setLowPriority();
if (isUnixTerminalDisabled()) if (m_setup->m_unixTerminalDisabled)
m_process->setUnixTerminalDisabled(); m_process->setUnixTerminalDisabled();
m_process->start(program, arguments, handler->openMode()); m_process->start(program, arguments, handler->openMode());
handler->handleProcessStart(); handler->handleProcessStart();
} }
void terminate() override void terminate() override
{ m_process->terminate(); } { m_process->terminate(); }
void kill() override void kill() override
@@ -408,11 +400,6 @@ public:
qint64 write(const QByteArray &data) override qint64 write(const QByteArray &data) override
{ return m_process->write(data); } { return m_process->write(data); }
void setStandardInputFile(const QString &fileName) override
{ m_process->setStandardInputFile(fileName); }
void setProcessChannelMode(QProcess::ProcessChannelMode mode) override
{ m_process->setProcessChannelMode(mode); }
QString program() const override QString program() const override
{ return m_process->program(); } { return m_process->program(); }
QProcess::ProcessError error() const override QProcess::ProcessError error() const override
@@ -484,25 +471,27 @@ public:
void setProcessEnvironment(const QProcessEnvironment &environment) override void setProcessEnvironment(const QProcessEnvironment &environment) override
{ m_handle->setProcessEnvironment(environment); } { m_handle->setProcessEnvironment(environment); }
void setWorkingDirectory(const QString &dir) override { m_handle->setWorkingDirectory(dir); } void setWorkingDirectory(const QString &dir) override { m_handle->setWorkingDirectory(dir); }
void start(const QString &program, const QStringList &arguments, const QByteArray &writeData) override void start(const QString &program, const QStringList &arguments, const QByteArray &writeData) override
{ {
if (isBelowNormalPriority()) m_handle->setStandardInputFile(m_setup->m_standardInputFile);
m_handle->setProcessChannelMode(m_setup->m_procesChannelMode);
m_handle->setErrorString(m_setup->m_initialErrorString);
if (m_setup->m_belowNormalPriority)
m_handle->setBelowNormalPriority(); m_handle->setBelowNormalPriority();
m_handle->setNativeArguments(nativeArguments()); m_handle->setNativeArguments(m_setup->m_nativeArguments);
if (isLowPriority()) if (m_setup->m_lowPriority)
m_handle->setLowPriority(); m_handle->setLowPriority();
if (isUnixTerminalDisabled()) if (m_setup->m_unixTerminalDisabled)
m_handle->setUnixTerminalDisabled(); m_handle->setUnixTerminalDisabled();
m_handle->start(program, arguments, writeData); m_handle->start(program, arguments, writeData);
} }
void terminate() override { cancel(); } // TODO: what are differences among terminate, kill and close? void terminate() override { cancel(); } // TODO: what are differences among terminate, kill and close?
void kill() override { cancel(); } // TODO: see above void kill() override { cancel(); } // TODO: see above
void close() override { cancel(); } // TODO: see above void close() override { cancel(); } // TODO: see above
qint64 write(const QByteArray &data) override { return m_handle->write(data); } qint64 write(const QByteArray &data) override { return m_handle->write(data); }
void setStandardInputFile(const QString &fileName) override { m_handle->setStandardInputFile(fileName); }
void setProcessChannelMode(QProcess::ProcessChannelMode mode) override { m_handle->setProcessChannelMode(mode); }
QString program() const override { return m_handle->program(); } QString program() const override { return m_handle->program(); }
QProcess::ProcessError error() const override { return m_handle->error(); } QProcess::ProcessError error() const override { return m_handle->error(); }
QProcess::ProcessState state() const override { return m_handle->state(); } QProcess::ProcessState state() const override { return m_handle->state(); }
@@ -536,14 +525,22 @@ void ProcessLauncherImpl::cancel()
m_handle->cancel(); m_handle->cancel();
} }
static ProcessInterface *newProcessInstance(QObject *parent, QtcProcess::ProcessImpl processImpl, static QtcProcess::ProcessImpl defaultProcessImpl()
ProcessMode mode, QtcProcess::TerminalMode terminalMode)
{ {
if (terminalMode != QtcProcess::TerminalOff) if (qEnvironmentVariableIsSet("QTC_USE_QPROCESS"))
return new TerminalImpl(parent, processImpl, terminalMode); return QtcProcess::QProcessImpl;
if (processImpl == QtcProcess::QProcessImpl) return QtcProcess::ProcessLauncherImpl;
return new QProcessImpl(parent, mode); }
return new ProcessLauncherImpl(parent, mode);
static ProcessInterface *newProcessInstance(QObject *parent, const QtcProcess::Setup &setup)
{
if (setup.terminalMode != QtcProcess::TerminalOff)
return new TerminalImpl(parent, setup.processImpl, setup.terminalMode);
const QtcProcess::ProcessImpl impl = setup.processImpl == QtcProcess::DefaultImpl
? defaultProcessImpl() : setup.processImpl;
if (impl == QtcProcess::QProcessImpl)
return new QProcessImpl(parent, setup.processMode);
return new ProcessLauncherImpl(parent, setup.processMode);
} }
class QtcProcessPrivate : public QObject class QtcProcessPrivate : public QObject
@@ -555,16 +552,20 @@ public:
OtherFailure OtherFailure
}; };
explicit QtcProcessPrivate(QtcProcess *parent, explicit QtcProcessPrivate(QtcProcess *parent, const QtcProcess::Setup &processSetup)
QtcProcess::ProcessImpl processImpl,
ProcessMode processMode,
QtcProcess::TerminalMode terminalMode)
: QObject(parent) : QObject(parent)
, q(parent) , q(parent)
, m_process(newProcessInstance(parent, processImpl, processMode, terminalMode)) , m_processSetup(processSetup)
, m_processMode(processMode) {}
, m_terminalMode(terminalMode)
void ensureProcessInstanceExists()
{ {
if (m_process)
return;
m_process = newProcessInstance(parent(), m_processSetup);
m_process->m_setup = &m_setup;
connect(m_process, &ProcessInterface::started, connect(m_process, &ProcessInterface::started,
q, &QtcProcess::started); q, &QtcProcess::started);
connect(m_process, &ProcessInterface::finished, connect(m_process, &ProcessInterface::finished,
@@ -610,6 +611,7 @@ public:
qCDebug(processLog) << "STARTING PROCESS: " << ++n << " " << commandLine.toUserOutput(); qCDebug(processLog) << "STARTING PROCESS: " << ++n << " " << commandLine.toUserOutput();
} }
ensureProcessInstanceExists();
m_process->setProcessEnvironment(environment.toProcessEnvironment()); m_process->setProcessEnvironment(environment.toProcessEnvironment());
m_process->setWorkingDirectory(workingDirectory.path()); m_process->setWorkingDirectory(workingDirectory.path());
@@ -621,13 +623,11 @@ public:
if (commandLine.executable().osType() == OsTypeWindows) { if (commandLine.executable().osType() == OsTypeWindows) {
QString args; QString args;
if (m_useCtrlCStub) { if (m_useCtrlCStub) {
if (m_process->isLowPriority()) if (m_setup.m_lowPriority)
ProcessArgs::addArg(&args, "-nice"); ProcessArgs::addArg(&args, "-nice");
ProcessArgs::addArg(&args, QDir::toNativeSeparators(commandString)); ProcessArgs::addArg(&args, QDir::toNativeSeparators(commandString));
commandString = QCoreApplication::applicationDirPath() commandString = QCoreApplication::applicationDirPath()
+ QLatin1String("/qtcreator_ctrlc_stub.exe"); + QLatin1String("/qtcreator_ctrlc_stub.exe");
} else if (m_process->isLowPriority()) {
m_process->setBelowNormalPriority();
} }
ProcessArgs::addArgs(&args, arguments.toWindowsArgs()); ProcessArgs::addArgs(&args, arguments.toWindowsArgs());
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
@@ -651,6 +651,7 @@ public:
void start(const QString &program, const QStringList &arguments, void start(const QString &program, const QStringList &arguments,
const FilePath &workingDirectory, const QByteArray &writeData) const FilePath &workingDirectory, const QByteArray &writeData)
{ {
ensureProcessInstanceExists();
const FilePath programFilePath = resolve(workingDirectory, FilePath::fromString(program)); const FilePath programFilePath = resolve(workingDirectory, FilePath::fromString(program));
if (programFilePath.exists() && programFilePath.isExecutableFile()) { if (programFilePath.exists() && programFilePath.isExecutableFile()) {
s_start.measureAndRun(&ProcessInterface::start, m_process, program, arguments, writeData); s_start.measureAndRun(&ProcessInterface::start, m_process, program, arguments, writeData);
@@ -689,9 +690,8 @@ public:
} }
QtcProcess *q; QtcProcess *q;
ProcessInterface *m_process; ProcessInterface *m_process = nullptr;
const ProcessMode m_processMode; const QtcProcess::Setup m_processSetup;
const QtcProcess::TerminalMode m_terminalMode;
CommandLine m_commandLine; CommandLine m_commandLine;
FilePath m_workingDirectory; FilePath m_workingDirectory;
Environment m_environment; Environment m_environment;
@@ -699,6 +699,7 @@ public:
bool m_runAsRoot = false; bool m_runAsRoot = false;
bool m_haveEnv = false; bool m_haveEnv = false;
bool m_useCtrlCStub = false; bool m_useCtrlCStub = false;
ProcessSetupData m_setup;
void slotTimeout(); void slotTimeout();
void slotFinished(int exitCode, QProcess::ExitStatus e); void slotFinished(int exitCode, QProcess::ExitStatus e);
@@ -751,18 +752,9 @@ QtcProcess::Result QtcProcessPrivate::interpretExitCode(int exitCode)
\sa Utils::ProcessArgs \sa Utils::ProcessArgs
*/ */
static QtcProcess::ProcessImpl defaultProcessImpl()
{
if (qEnvironmentVariableIsSet("QTC_USE_QPROCESS"))
return QtcProcess::QProcessImpl;
return QtcProcess::ProcessLauncherImpl;
}
QtcProcess::QtcProcess(const Setup &setup, QObject *parent) QtcProcess::QtcProcess(const Setup &setup, QObject *parent)
: QObject(parent), : QObject(parent),
d(new QtcProcessPrivate(this, d(new QtcProcessPrivate(this, setup))
setup.processImpl == DefaultImpl ? defaultProcessImpl() : setup.processImpl,
setup.processMode, setup.terminalMode))
{ {
static int qProcessExitStatusMeta = qRegisterMetaType<QProcess::ExitStatus>(); static int qProcessExitStatusMeta = qRegisterMetaType<QProcess::ExitStatus>();
static int qProcessProcessErrorMeta = qRegisterMetaType<QProcess::ProcessError>(); static int qProcessProcessErrorMeta = qRegisterMetaType<QProcess::ProcessError>();
@@ -781,12 +773,12 @@ QtcProcess::~QtcProcess()
ProcessMode QtcProcess::processMode() const ProcessMode QtcProcess::processMode() const
{ {
return d->m_processMode; return d->m_processSetup.processMode;
} }
QtcProcess::TerminalMode QtcProcess::terminalMode() const QtcProcess::TerminalMode QtcProcess::terminalMode() const
{ {
return d->m_terminalMode; return d->m_processSetup.terminalMode;
} }
void QtcProcess::setEnvironment(const Environment &env) void QtcProcess::setEnvironment(const Environment &env)
@@ -851,6 +843,7 @@ void QtcProcess::setUseCtrlCStub(bool enabled)
void QtcProcess::start() void QtcProcess::start()
{ {
d->ensureProcessInstanceExists();
if (d->m_commandLine.executable().needsDevice()) { if (d->m_commandLine.executable().needsDevice()) {
QTC_ASSERT(s_deviceHooks.startProcessHook, return); QTC_ASSERT(s_deviceHooks.startProcessHook, return);
s_deviceHooks.startProcessHook(*this); s_deviceHooks.startProcessHook(*this);
@@ -897,7 +890,8 @@ void QtcProcess::terminate()
EnumWindows(sendShutDownMessageToAllWindowsOfProcess_enumWnd, processId()); EnumWindows(sendShutDownMessageToAllWindowsOfProcess_enumWnd, processId());
else else
#endif #endif
d->m_process->terminate(); if (d->m_process)
d->m_process->terminate();
} }
void QtcProcess::interrupt() void QtcProcess::interrupt()
@@ -918,17 +912,17 @@ bool QtcProcess::startDetached(const CommandLine &cmd, const FilePath &workingDi
void QtcProcess::setLowPriority() void QtcProcess::setLowPriority()
{ {
d->m_process->setLowPriority(); d->m_setup.m_lowPriority = true;
} }
void QtcProcess::setDisableUnixTerminal() void QtcProcess::setDisableUnixTerminal()
{ {
d->m_process->setUnixTerminalDisabled(); d->m_setup.m_unixTerminalDisabled = true;
} }
void QtcProcess::setAbortOnMetaChars(bool abort) void QtcProcess::setAbortOnMetaChars(bool abort)
{ {
d->m_process->setAbortOnMetaChars(abort); d->m_setup.m_abortOnMetaChars = abort;
} }
void QtcProcess::setRunAsRoot(bool on) void QtcProcess::setRunAsRoot(bool on)
@@ -943,7 +937,7 @@ bool QtcProcess::isRunAsRoot() const
void QtcProcess::setStandardInputFile(const QString &inputFile) void QtcProcess::setStandardInputFile(const QString &inputFile)
{ {
d->m_process->setStandardInputFile(inputFile); d->m_setup.m_standardInputFile = inputFile;
} }
QString QtcProcess::toStandaloneCommandLine() const QString QtcProcess::toStandaloneCommandLine() const
@@ -1079,7 +1073,9 @@ int QtcProcess::exitCode() const
{ {
if (d->m_startFailure == QtcProcessPrivate::WrongFileNameFailure) if (d->m_startFailure == QtcProcessPrivate::WrongFileNameFailure)
return 255; // This code is being returned by QProcess when FailedToStart error occurred return 255; // This code is being returned by QProcess when FailedToStart error occurred
return d->m_process->exitCode(); if (d->m_process)
return d->m_process->exitCode();
return 0;
} }
@@ -1174,34 +1170,42 @@ Environment QtcProcess::systemEnvironmentForBinary(const FilePath &filePath)
void QtcProcess::kickoffProcess() void QtcProcess::kickoffProcess()
{ {
d->m_process->kickoffProcess(); if (d->m_process)
d->m_process->kickoffProcess();
} }
void QtcProcess::interruptProcess() void QtcProcess::interruptProcess()
{ {
d->m_process->interruptProcess(); if (d->m_process)
d->m_process->interruptProcess();
} }
qint64 QtcProcess::applicationMainThreadID() const qint64 QtcProcess::applicationMainThreadID() const
{ {
return d->m_process->applicationMainThreadID(); if (d->m_process)
return d->m_process->applicationMainThreadID();
return -1;
} }
void QtcProcess::setProcessChannelMode(QProcess::ProcessChannelMode mode) void QtcProcess::setProcessChannelMode(QProcess::ProcessChannelMode mode)
{ {
d->m_process->setProcessChannelMode(mode); d->m_setup.m_procesChannelMode = mode;
} }
QProcess::ProcessError QtcProcess::error() const QProcess::ProcessError QtcProcess::error() const
{ {
if (d->m_startFailure == QtcProcessPrivate::WrongFileNameFailure) if (d->m_startFailure == QtcProcessPrivate::WrongFileNameFailure)
return QProcess::FailedToStart; return QProcess::FailedToStart;
return d->m_process->error(); if (d->m_process)
return d->m_process->error();
return QProcess::UnknownError;
} }
QProcess::ProcessState QtcProcess::state() const QProcess::ProcessState QtcProcess::state() const
{ {
return d->m_process->state(); if (d->m_process)
return d->m_process->state();
return QProcess::NotRunning;
} }
bool QtcProcess::isRunning() const bool QtcProcess::isRunning() const
@@ -1211,31 +1215,41 @@ bool QtcProcess::isRunning() const
QString QtcProcess::errorString() const QString QtcProcess::errorString() const
{ {
return d->m_process->errorString(); if (d->m_process)
return d->m_process->errorString();
return d->m_setup.m_initialErrorString;
} }
void QtcProcess::setErrorString(const QString &str) void QtcProcess::setErrorString(const QString &str)
{ {
d->m_process->setErrorString(str); if (d->m_process)
d->m_process->setErrorString(str);
else
d->m_setup.m_initialErrorString = str;
} }
qint64 QtcProcess::processId() const qint64 QtcProcess::processId() const
{ {
return d->m_process->processId(); if (d->m_process)
return d->m_process->processId();
return 0;
} }
bool QtcProcess::waitForStarted(int msecs) bool QtcProcess::waitForStarted(int msecs)
{ {
QTC_ASSERT(d->m_process, return false);
return s_waitForStarted.measureAndRun(&ProcessInterface::waitForStarted, d->m_process, msecs); return s_waitForStarted.measureAndRun(&ProcessInterface::waitForStarted, d->m_process, msecs);
} }
bool QtcProcess::waitForReadyRead(int msecs) bool QtcProcess::waitForReadyRead(int msecs)
{ {
QTC_ASSERT(d->m_process, return false);
return d->m_process->waitForReadyRead(msecs); return d->m_process->waitForReadyRead(msecs);
} }
bool QtcProcess::waitForFinished(int msecs) bool QtcProcess::waitForFinished(int msecs)
{ {
QTC_ASSERT(d->m_process, return false);
return d->m_process->waitForFinished(msecs); return d->m_process->waitForFinished(msecs);
} }
@@ -1255,23 +1269,28 @@ QByteArray QtcProcess::readAllStandardError()
QProcess::ExitStatus QtcProcess::exitStatus() const QProcess::ExitStatus QtcProcess::exitStatus() const
{ {
return d->m_process->exitStatus(); if (d->m_process)
return d->m_process->exitStatus();
return QProcess::ExitStatus::NormalExit;
} }
void QtcProcess::kill() void QtcProcess::kill()
{ {
d->m_process->kill(); if (d->m_process)
d->m_process->kill();
} }
qint64 QtcProcess::write(const QByteArray &input) qint64 QtcProcess::write(const QByteArray &input)
{ {
QTC_ASSERT(processMode() == ProcessMode::Writer, return -1); QTC_ASSERT(processMode() == ProcessMode::Writer, return -1);
QTC_ASSERT(d->m_process, return -1);
return d->m_process->write(input); return d->m_process->write(input);
} }
void QtcProcess::close() void QtcProcess::close()
{ {
d->m_process->close(); if (d->m_process)
d->m_process->close();
} }
void QtcProcess::beginFeed() void QtcProcess::beginFeed()
@@ -1530,9 +1549,8 @@ void QtcProcess::runBlocking(QtcProcess::EventLoopMode eventLoopMode)
<< " process user events: " << (eventLoopMode == QtcProcess::WithEventLoop); << " process user events: " << (eventLoopMode == QtcProcess::WithEventLoop);
ExecuteOnDestruction logResult([this] { qCDebug(processLog) << *this; }); ExecuteOnDestruction logResult([this] { qCDebug(processLog) << *this; });
QtcProcess::start();
if (eventLoopMode == QtcProcess::WithEventLoop) { if (eventLoopMode == QtcProcess::WithEventLoop) {
QtcProcess::start();
// On Windows, start failure is triggered immediately if the // On Windows, start failure is triggered immediately if the
// executable cannot be found in the path. Do not start the // executable cannot be found in the path. Do not start the
// event loop in that case. // event loop in that case.
@@ -1560,7 +1578,6 @@ void QtcProcess::runBlocking(QtcProcess::EventLoopMode eventLoopMode)
#endif #endif
} }
} else { } else {
QtcProcess::start();
if (!waitForStarted(d->m_maxHangTimerCount * 1000)) { if (!waitForStarted(d->m_maxHangTimerCount * 1000)) {
d->m_result = QtcProcess::StartFailed; d->m_result = QtcProcess::StartFailed;
return; return;