forked from qt-creator/qt-creator
Introduce ProcessProxyInterface, enable data sharing
ProcessProxyInterface will be helpful when implementing public subclasses of ProcessInterface, like general ssh impl, linux specific impl, qnx specific, etc. ProcessProxyInterface is sharing private data between proxy and target. Change-Id: I8350837bb5f770d6605b860b146604cba5e6b592 Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
@@ -215,7 +215,7 @@ void CallerHandle::handleError(const ErrorSignal *launcherSignal)
|
|||||||
QTC_ASSERT(isCalledFromCallersThread(), return);
|
QTC_ASSERT(isCalledFromCallersThread(), return);
|
||||||
m_processState = QProcess::NotRunning;
|
m_processState = QProcess::NotRunning;
|
||||||
m_error = launcherSignal->error();
|
m_error = launcherSignal->error();
|
||||||
m_setup.m_errorString = launcherSignal->errorString();
|
m_setup->m_errorString = launcherSignal->errorString();
|
||||||
if (m_error == QProcess::FailedToStart)
|
if (m_error == QProcess::FailedToStart)
|
||||||
m_exitCode = 255; // This code is being returned by QProcess when FailedToStart error occurred
|
m_exitCode = 255; // This code is being returned by QProcess when FailedToStart error occurred
|
||||||
emit errorOccurred(m_error);
|
emit errorOccurred(m_error);
|
||||||
@@ -232,16 +232,16 @@ void CallerHandle::handleStarted(const StartedSignal *launcherSignal)
|
|||||||
void CallerHandle::handleReadyRead(const ReadyReadSignal *launcherSignal)
|
void CallerHandle::handleReadyRead(const ReadyReadSignal *launcherSignal)
|
||||||
{
|
{
|
||||||
QTC_ASSERT(isCalledFromCallersThread(), return);
|
QTC_ASSERT(isCalledFromCallersThread(), return);
|
||||||
if (m_setup.m_processChannelMode == QProcess::ForwardedOutputChannel
|
if (m_setup->m_processChannelMode == QProcess::ForwardedOutputChannel
|
||||||
|| m_setup.m_processChannelMode == QProcess::ForwardedChannels) {
|
|| m_setup->m_processChannelMode == QProcess::ForwardedChannels) {
|
||||||
std::cout << launcherSignal->stdOut().constData();
|
std::cout << launcherSignal->stdOut().constData();
|
||||||
} else {
|
} else {
|
||||||
m_stdout += launcherSignal->stdOut();
|
m_stdout += launcherSignal->stdOut();
|
||||||
if (!m_stdout.isEmpty())
|
if (!m_stdout.isEmpty())
|
||||||
emit readyReadStandardOutput();
|
emit readyReadStandardOutput();
|
||||||
}
|
}
|
||||||
if (m_setup.m_processChannelMode == QProcess::ForwardedErrorChannel
|
if (m_setup->m_processChannelMode == QProcess::ForwardedErrorChannel
|
||||||
|| m_setup.m_processChannelMode == QProcess::ForwardedChannels) {
|
|| m_setup->m_processChannelMode == QProcess::ForwardedChannels) {
|
||||||
std::cerr << launcherSignal->stdErr().constData();
|
std::cerr << launcherSignal->stdErr().constData();
|
||||||
} else {
|
} else {
|
||||||
m_stderr += launcherSignal->stdErr();
|
m_stderr += launcherSignal->stdErr();
|
||||||
@@ -293,8 +293,8 @@ void CallerHandle::cancel()
|
|||||||
case QProcess::NotRunning:
|
case QProcess::NotRunning:
|
||||||
break;
|
break;
|
||||||
case QProcess::Starting:
|
case QProcess::Starting:
|
||||||
m_setup.m_errorString = QCoreApplication::translate("Utils::LauncherHandle",
|
m_setup->m_errorString = QCoreApplication::translate("Utils::LauncherHandle",
|
||||||
"Process was canceled before it was started.");
|
"Process was canceled before it was started.");
|
||||||
m_error = QProcess::FailedToStart;
|
m_error = QProcess::FailedToStart;
|
||||||
if (LauncherInterface::isReady()) // TODO: race condition with m_processState???
|
if (LauncherInterface::isReady()) // TODO: race condition with m_processState???
|
||||||
sendPacket(StopProcessPacket(m_token));
|
sendPacket(StopProcessPacket(m_token));
|
||||||
@@ -337,13 +337,13 @@ int CallerHandle::exitCode() const
|
|||||||
QString CallerHandle::errorString() const
|
QString CallerHandle::errorString() const
|
||||||
{
|
{
|
||||||
QTC_ASSERT(isCalledFromCallersThread(), return {});
|
QTC_ASSERT(isCalledFromCallersThread(), return {});
|
||||||
return m_setup.m_errorString;
|
return m_setup->m_errorString;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CallerHandle::setErrorString(const QString &str)
|
void CallerHandle::setErrorString(const QString &str)
|
||||||
{
|
{
|
||||||
QTC_ASSERT(isCalledFromCallersThread(), return);
|
QTC_ASSERT(isCalledFromCallersThread(), return);
|
||||||
m_setup.m_errorString = str;
|
m_setup->m_errorString = str;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CallerHandle::start(const QString &program, const QStringList &arguments)
|
void CallerHandle::start(const QString &program, const QStringList &arguments)
|
||||||
@@ -374,16 +374,16 @@ void CallerHandle::start(const QString &program, const QStringList &arguments)
|
|||||||
StartProcessPacket *p = new StartProcessPacket(m_token);
|
StartProcessPacket *p = new StartProcessPacket(m_token);
|
||||||
p->command = m_command;
|
p->command = m_command;
|
||||||
p->arguments = m_arguments;
|
p->arguments = m_arguments;
|
||||||
p->env = m_setup.m_environment.toStringList();
|
p->env = m_setup->m_environment.toStringList();
|
||||||
p->workingDir = m_setup.m_workingDirectory.path();
|
p->workingDir = m_setup->m_workingDirectory.path();
|
||||||
p->processMode = m_setup.m_processMode;
|
p->processMode = m_setup->m_processMode;
|
||||||
p->writeData = m_setup.m_writeData;
|
p->writeData = m_setup->m_writeData;
|
||||||
p->processChannelMode = m_setup.m_processChannelMode;
|
p->processChannelMode = m_setup->m_processChannelMode;
|
||||||
p->standardInputFile = m_setup.m_standardInputFile;
|
p->standardInputFile = m_setup->m_standardInputFile;
|
||||||
p->belowNormalPriority = m_setup.m_belowNormalPriority;
|
p->belowNormalPriority = m_setup->m_belowNormalPriority;
|
||||||
p->nativeArguments = m_setup.m_nativeArguments;
|
p->nativeArguments = m_setup->m_nativeArguments;
|
||||||
p->lowPriority = m_setup.m_lowPriority;
|
p->lowPriority = m_setup->m_lowPriority;
|
||||||
p->unixTerminalDisabled = m_setup.m_unixTerminalDisabled;
|
p->unixTerminalDisabled = m_setup->m_unixTerminalDisabled;
|
||||||
m_startPacket.reset(p);
|
m_startPacket.reset(p);
|
||||||
if (LauncherInterface::isReady())
|
if (LauncherInterface::isReady())
|
||||||
doStart();
|
doStart();
|
||||||
@@ -443,7 +443,7 @@ QStringList CallerHandle::arguments() const
|
|||||||
return m_arguments;
|
return m_arguments;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CallerHandle::setProcessSetupData(const ProcessSetupData &setup)
|
void CallerHandle::setProcessSetupData(const ProcessSetupData::Ptr &setup)
|
||||||
{
|
{
|
||||||
QTC_ASSERT(isCalledFromCallersThread(), return);
|
QTC_ASSERT(isCalledFromCallersThread(), return);
|
||||||
m_setup = setup;
|
m_setup = setup;
|
||||||
|
@@ -111,7 +111,7 @@ public:
|
|||||||
QString program() const;
|
QString program() const;
|
||||||
// Called from caller's or launcher's thread.
|
// Called from caller's or launcher's thread.
|
||||||
QStringList arguments() const;
|
QStringList arguments() const;
|
||||||
void setProcessSetupData(const ProcessSetupData &setup);
|
void setProcessSetupData(const ProcessSetupData::Ptr &setup);
|
||||||
QProcess::ExitStatus exitStatus() const;
|
QProcess::ExitStatus exitStatus() const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
@@ -167,7 +167,7 @@ private:
|
|||||||
|
|
||||||
QString m_command;
|
QString m_command;
|
||||||
QStringList m_arguments;
|
QStringList m_arguments;
|
||||||
ProcessSetupData m_setup;
|
ProcessSetupData::Ptr m_setup;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Moved to the launcher thread, returned to caller's thread.
|
// Moved to the launcher thread, returned to caller's thread.
|
||||||
|
@@ -38,6 +38,8 @@ namespace Utils {
|
|||||||
class QTCREATOR_UTILS_EXPORT ProcessSetupData
|
class QTCREATOR_UTILS_EXPORT ProcessSetupData
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
using Ptr = std::shared_ptr<ProcessSetupData>;
|
||||||
|
|
||||||
ProcessImpl m_processImpl = ProcessImpl::Default;
|
ProcessImpl m_processImpl = ProcessImpl::Default;
|
||||||
ProcessMode m_processMode = ProcessMode::Reader;
|
ProcessMode m_processMode = ProcessMode::Reader;
|
||||||
TerminalMode m_terminalMode = TerminalMode::Off;
|
TerminalMode m_terminalMode = TerminalMode::Off;
|
||||||
@@ -67,7 +69,8 @@ class QTCREATOR_UTILS_EXPORT ProcessInterface : public QObject
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ProcessInterface(QObject *parent = nullptr) : QObject(parent) {}
|
ProcessInterface(QObject *parent = nullptr) : QObject(parent), m_setup(new ProcessSetupData) {}
|
||||||
|
ProcessInterface(ProcessSetupData::Ptr setup) : m_setup(setup) {}
|
||||||
|
|
||||||
virtual void start() = 0;
|
virtual void start() = 0;
|
||||||
virtual void terminate() = 0;
|
virtual void terminate() = 0;
|
||||||
@@ -103,8 +106,59 @@ signals:
|
|||||||
void readyReadStandardError();
|
void readyReadStandardError();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ProcessSetupData m_setup;
|
ProcessSetupData::Ptr m_setup;
|
||||||
|
friend class ProcessProxyInterface;
|
||||||
friend class QtcProcess;
|
friend class QtcProcess;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class QTCREATOR_UTILS_EXPORT ProcessProxyInterface : public ProcessInterface
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
ProcessProxyInterface(ProcessInterface *target)
|
||||||
|
: ProcessInterface(target->m_setup)
|
||||||
|
, m_target(target)
|
||||||
|
{
|
||||||
|
m_target->setParent(this);
|
||||||
|
connect(m_target, &ProcessInterface::started, this, &ProcessInterface::started);
|
||||||
|
connect(m_target, &ProcessInterface::finished, this, &ProcessInterface::finished);
|
||||||
|
connect(m_target, &ProcessInterface::errorOccurred, this, &ProcessInterface::errorOccurred);
|
||||||
|
connect(m_target, &ProcessInterface::readyReadStandardOutput,
|
||||||
|
this, &ProcessInterface::readyReadStandardOutput);
|
||||||
|
connect(m_target, &ProcessInterface::readyReadStandardError,
|
||||||
|
this, &ProcessInterface::readyReadStandardError);
|
||||||
|
}
|
||||||
|
|
||||||
|
void start() override { m_target->start(); }
|
||||||
|
void terminate() override { m_target->terminate(); }
|
||||||
|
void kill() override { m_target->kill(); }
|
||||||
|
void close() override { m_target->close(); }
|
||||||
|
|
||||||
|
QByteArray readAllStandardOutput() override { return m_target->readAllStandardOutput(); }
|
||||||
|
QByteArray readAllStandardError() override { return m_target->readAllStandardError(); }
|
||||||
|
qint64 write(const QByteArray &data) override { return m_target->write(data); }
|
||||||
|
|
||||||
|
qint64 processId() const override { return m_target->processId(); }
|
||||||
|
QProcess::ProcessState state() const override { return m_target->state(); }
|
||||||
|
int exitCode() const override { return m_target->exitCode(); }
|
||||||
|
QProcess::ExitStatus exitStatus() const override { return m_target->exitStatus(); }
|
||||||
|
|
||||||
|
QProcess::ProcessError error() const override { return m_target->error(); }
|
||||||
|
QString errorString() const override { return m_target->errorString(); }
|
||||||
|
void setErrorString(const QString &str) override { m_target->setErrorString(str); }
|
||||||
|
|
||||||
|
bool waitForStarted(int msecs) override { return m_target->waitForStarted(msecs); }
|
||||||
|
bool waitForReadyRead(int msecs) override { return m_target->waitForReadyRead(msecs); }
|
||||||
|
bool waitForFinished(int msecs) override { return m_target->waitForFinished(msecs); }
|
||||||
|
|
||||||
|
void kickoffProcess() override { m_target->kickoffProcess(); }
|
||||||
|
void interruptProcess() override { m_target->interruptProcess(); }
|
||||||
|
qint64 applicationMainThreadID() const override { return m_target->applicationMainThreadID(); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
ProcessInterface *m_target;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace Utils
|
} // namespace Utils
|
||||||
|
@@ -240,12 +240,12 @@ public:
|
|||||||
|
|
||||||
void start() override
|
void start() override
|
||||||
{
|
{
|
||||||
m_terminal.setProcessImpl(m_setup.m_processImpl);
|
m_terminal.setProcessImpl(m_setup->m_processImpl);
|
||||||
m_terminal.setTerminalMode(m_setup.m_terminalMode);
|
m_terminal.setTerminalMode(m_setup->m_terminalMode);
|
||||||
m_terminal.setAbortOnMetaChars(m_setup.m_abortOnMetaChars);
|
m_terminal.setAbortOnMetaChars(m_setup->m_abortOnMetaChars);
|
||||||
m_terminal.setCommand(m_setup.m_commandLine);
|
m_terminal.setCommand(m_setup->m_commandLine);
|
||||||
m_terminal.setWorkingDirectory(m_setup.m_workingDirectory);
|
m_terminal.setWorkingDirectory(m_setup->m_workingDirectory);
|
||||||
m_terminal.setEnvironment(m_setup.m_environment);
|
m_terminal.setEnvironment(m_setup->m_environment);
|
||||||
m_terminal.start();
|
m_terminal.start();
|
||||||
}
|
}
|
||||||
void terminate() override { m_terminal.stopProcess(); }
|
void terminate() override { m_terminal.stopProcess(); }
|
||||||
@@ -312,7 +312,7 @@ void DefaultImpl::defaultStart()
|
|||||||
<< "Process " << currentNumber << " starting ("
|
<< "Process " << currentNumber << " starting ("
|
||||||
<< qPrintable(blockingMessage(property(QTC_PROCESS_BLOCKING_TYPE)))
|
<< qPrintable(blockingMessage(property(QTC_PROCESS_BLOCKING_TYPE)))
|
||||||
<< "): "
|
<< "): "
|
||||||
<< m_setup.m_commandLine.toUserOutput();
|
<< m_setup->m_commandLine.toUserOutput();
|
||||||
setProperty(QTC_PROCESS_NUMBER, currentNumber);
|
setProperty(QTC_PROCESS_NUMBER, currentNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -327,26 +327,26 @@ void DefaultImpl::defaultStart()
|
|||||||
|
|
||||||
bool DefaultImpl::dissolveCommand(QString *program, QStringList *arguments)
|
bool DefaultImpl::dissolveCommand(QString *program, QStringList *arguments)
|
||||||
{
|
{
|
||||||
const CommandLine &commandLine = m_setup.m_commandLine;
|
const CommandLine &commandLine = m_setup->m_commandLine;
|
||||||
QString commandString;
|
QString commandString;
|
||||||
ProcessArgs processArgs;
|
ProcessArgs processArgs;
|
||||||
const bool success = ProcessArgs::prepareCommand(commandLine, &commandString, &processArgs,
|
const bool success = ProcessArgs::prepareCommand(commandLine, &commandString, &processArgs,
|
||||||
&m_setup.m_environment,
|
&m_setup->m_environment,
|
||||||
&m_setup.m_workingDirectory);
|
&m_setup->m_workingDirectory);
|
||||||
|
|
||||||
if (commandLine.executable().osType() == OsTypeWindows) {
|
if (commandLine.executable().osType() == OsTypeWindows) {
|
||||||
QString args;
|
QString args;
|
||||||
if (m_setup.m_useCtrlCStub) {
|
if (m_setup->m_useCtrlCStub) {
|
||||||
if (m_setup.m_lowPriority)
|
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_setup.m_lowPriority) {
|
} else if (m_setup->m_lowPriority) {
|
||||||
m_setup.m_belowNormalPriority = true;
|
m_setup->m_belowNormalPriority = true;
|
||||||
}
|
}
|
||||||
ProcessArgs::addArgs(&args, processArgs.toWindowsArgs());
|
ProcessArgs::addArgs(&args, processArgs.toWindowsArgs());
|
||||||
m_setup.m_nativeArguments = args;
|
m_setup->m_nativeArguments = args;
|
||||||
// Note: Arguments set with setNativeArgs will be appended to the ones
|
// Note: Arguments set with setNativeArgs will be appended to the ones
|
||||||
// passed with start() below.
|
// passed with start() below.
|
||||||
*arguments = QStringList();
|
*arguments = QStringList();
|
||||||
@@ -376,7 +376,7 @@ static FilePath resolve(const FilePath &workingDir, const FilePath &filePath)
|
|||||||
|
|
||||||
bool DefaultImpl::ensureProgramExists(const QString &program)
|
bool DefaultImpl::ensureProgramExists(const QString &program)
|
||||||
{
|
{
|
||||||
const FilePath programFilePath = resolve(m_setup.m_workingDirectory,
|
const FilePath programFilePath = resolve(m_setup->m_workingDirectory,
|
||||||
FilePath::fromString(program));
|
FilePath::fromString(program));
|
||||||
if (programFilePath.exists() && programFilePath.isExecutableFile())
|
if (programFilePath.exists() && programFilePath.isExecutableFile())
|
||||||
return true;
|
return true;
|
||||||
@@ -446,19 +446,19 @@ private:
|
|||||||
void doDefaultStart(const QString &program, const QStringList &arguments) override
|
void doDefaultStart(const QString &program, const QStringList &arguments) override
|
||||||
{
|
{
|
||||||
ProcessStartHandler *handler = m_process->processStartHandler();
|
ProcessStartHandler *handler = m_process->processStartHandler();
|
||||||
handler->setProcessMode(m_setup.m_processMode);
|
handler->setProcessMode(m_setup->m_processMode);
|
||||||
handler->setWriteData(m_setup.m_writeData);
|
handler->setWriteData(m_setup->m_writeData);
|
||||||
if (m_setup.m_belowNormalPriority)
|
if (m_setup->m_belowNormalPriority)
|
||||||
handler->setBelowNormalPriority();
|
handler->setBelowNormalPriority();
|
||||||
handler->setNativeArguments(m_setup.m_nativeArguments);
|
handler->setNativeArguments(m_setup->m_nativeArguments);
|
||||||
m_process->setProcessEnvironment(m_setup.m_environment.toProcessEnvironment());
|
m_process->setProcessEnvironment(m_setup->m_environment.toProcessEnvironment());
|
||||||
m_process->setWorkingDirectory(m_setup.m_workingDirectory.path());
|
m_process->setWorkingDirectory(m_setup->m_workingDirectory.path());
|
||||||
m_process->setStandardInputFile(m_setup.m_standardInputFile);
|
m_process->setStandardInputFile(m_setup->m_standardInputFile);
|
||||||
m_process->setProcessChannelMode(m_setup.m_processChannelMode);
|
m_process->setProcessChannelMode(m_setup->m_processChannelMode);
|
||||||
m_process->setErrorString(m_setup.m_errorString);
|
m_process->setErrorString(m_setup->m_errorString);
|
||||||
if (m_setup.m_lowPriority)
|
if (m_setup->m_lowPriority)
|
||||||
m_process->setLowPriority();
|
m_process->setLowPriority();
|
||||||
if (m_setup.m_unixTerminalDisabled)
|
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();
|
||||||
@@ -560,7 +560,7 @@ public:
|
|||||||
OtherFailure
|
OtherFailure
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit QtcProcessPrivate(QtcProcess *parent, ProcessSetupData &setup)
|
explicit QtcProcessPrivate(QtcProcess *parent, const ProcessSetupData::Ptr &setup)
|
||||||
: QObject(parent)
|
: QObject(parent)
|
||||||
, q(parent)
|
, q(parent)
|
||||||
, m_setup(setup)
|
, m_setup(setup)
|
||||||
@@ -568,11 +568,11 @@ public:
|
|||||||
|
|
||||||
ProcessInterface *createProcessInterface()
|
ProcessInterface *createProcessInterface()
|
||||||
{
|
{
|
||||||
if (m_setup.m_terminalMode != TerminalMode::Off)
|
if (m_setup->m_terminalMode != TerminalMode::Off)
|
||||||
return new TerminalImpl();
|
return new TerminalImpl();
|
||||||
|
|
||||||
const ProcessImpl impl = m_setup.m_processImpl == ProcessImpl::Default
|
const ProcessImpl impl = m_setup->m_processImpl == ProcessImpl::Default
|
||||||
? defaultProcessImpl() : m_setup.m_processImpl;
|
? defaultProcessImpl() : m_setup->m_processImpl;
|
||||||
if (impl == ProcessImpl::QProcess)
|
if (impl == ProcessImpl::QProcess)
|
||||||
return new QProcessImpl();
|
return new QProcessImpl();
|
||||||
return new ProcessLauncherImpl();
|
return new ProcessLauncherImpl();
|
||||||
@@ -581,7 +581,7 @@ public:
|
|||||||
void setProcessInterface(ProcessInterface *process)
|
void setProcessInterface(ProcessInterface *process)
|
||||||
{
|
{
|
||||||
m_process.reset(process);
|
m_process.reset(process);
|
||||||
m_setup.m_errorString.clear();
|
m_setup->m_errorString.clear();
|
||||||
m_process->setParent(this);
|
m_process->setParent(this);
|
||||||
|
|
||||||
connect(m_process.get(), &ProcessInterface::started,
|
connect(m_process.get(), &ProcessInterface::started,
|
||||||
@@ -612,21 +612,21 @@ public:
|
|||||||
|
|
||||||
CommandLine fullCommandLine() const
|
CommandLine fullCommandLine() const
|
||||||
{
|
{
|
||||||
if (!m_setup.m_runAsRoot || HostOsInfo::isWindowsHost())
|
if (!m_setup->m_runAsRoot || HostOsInfo::isWindowsHost())
|
||||||
return m_setup.m_commandLine;
|
return m_setup->m_commandLine;
|
||||||
CommandLine rootCommand("sudo", {"-A"});
|
CommandLine rootCommand("sudo", {"-A"});
|
||||||
rootCommand.addCommandLineAsArgs(m_setup.m_commandLine);
|
rootCommand.addCommandLineAsArgs(m_setup->m_commandLine);
|
||||||
return rootCommand;
|
return rootCommand;
|
||||||
}
|
}
|
||||||
|
|
||||||
Environment fullEnvironment() const
|
Environment fullEnvironment() const
|
||||||
{
|
{
|
||||||
Environment env;
|
Environment env;
|
||||||
if (m_setup.m_haveEnv) {
|
if (m_setup->m_haveEnv) {
|
||||||
if (m_setup.m_environment.size() == 0)
|
if (m_setup->m_environment.size() == 0)
|
||||||
qWarning("QtcProcess::start: Empty environment set when running '%s'.",
|
qWarning("QtcProcess::start: Empty environment set when running '%s'.",
|
||||||
qPrintable(m_setup.m_commandLine.executable().toString()));
|
qPrintable(m_setup->m_commandLine.executable().toString()));
|
||||||
env = m_setup.m_environment;
|
env = m_setup->m_environment;
|
||||||
} else {
|
} else {
|
||||||
env = Environment::systemEnvironment();
|
env = Environment::systemEnvironment();
|
||||||
}
|
}
|
||||||
@@ -639,7 +639,7 @@ public:
|
|||||||
|
|
||||||
QtcProcess *q;
|
QtcProcess *q;
|
||||||
std::unique_ptr<ProcessInterface> m_process;
|
std::unique_ptr<ProcessInterface> m_process;
|
||||||
ProcessSetupData &m_setup;
|
ProcessSetupData::Ptr m_setup;
|
||||||
|
|
||||||
void slotTimeout();
|
void slotTimeout();
|
||||||
void slotFinished();
|
void slotFinished();
|
||||||
@@ -770,90 +770,91 @@ void QtcProcess::emitErrorOccurred(QProcess::ProcessError error)
|
|||||||
void QtcProcess::setProcessInterface(ProcessInterface *interface)
|
void QtcProcess::setProcessInterface(ProcessInterface *interface)
|
||||||
{
|
{
|
||||||
d->setProcessInterface(interface);
|
d->setProcessInterface(interface);
|
||||||
d->m_process->m_setup = d->m_setup;
|
// Make a copy, don't share, until we get rid of fullCommandLine() and fullEnvironment()
|
||||||
|
*d->m_process->m_setup = *d->m_setup;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtcProcess::setProcessImpl(ProcessImpl processImpl)
|
void QtcProcess::setProcessImpl(ProcessImpl processImpl)
|
||||||
{
|
{
|
||||||
d->m_setup.m_processImpl = processImpl;
|
d->m_setup->m_processImpl = processImpl;
|
||||||
}
|
}
|
||||||
|
|
||||||
ProcessMode QtcProcess::processMode() const
|
ProcessMode QtcProcess::processMode() const
|
||||||
{
|
{
|
||||||
return d->m_setup.m_processMode;
|
return d->m_setup->m_processMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtcProcess::setTerminalMode(TerminalMode mode)
|
void QtcProcess::setTerminalMode(TerminalMode mode)
|
||||||
{
|
{
|
||||||
d->m_setup.m_terminalMode = mode;
|
d->m_setup->m_terminalMode = mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
TerminalMode QtcProcess::terminalMode() const
|
TerminalMode QtcProcess::terminalMode() const
|
||||||
{
|
{
|
||||||
return d->m_setup.m_terminalMode;
|
return d->m_setup->m_terminalMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtcProcess::setProcessMode(ProcessMode processMode)
|
void QtcProcess::setProcessMode(ProcessMode processMode)
|
||||||
{
|
{
|
||||||
d->m_setup.m_processMode = processMode;
|
d->m_setup->m_processMode = processMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtcProcess::setEnvironment(const Environment &env)
|
void QtcProcess::setEnvironment(const Environment &env)
|
||||||
{
|
{
|
||||||
d->m_setup.m_environment = env;
|
d->m_setup->m_environment = env;
|
||||||
d->m_setup.m_haveEnv = true;
|
d->m_setup->m_haveEnv = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtcProcess::unsetEnvironment()
|
void QtcProcess::unsetEnvironment()
|
||||||
{
|
{
|
||||||
d->m_setup.m_environment = Environment();
|
d->m_setup->m_environment = Environment();
|
||||||
d->m_setup.m_haveEnv = false;
|
d->m_setup->m_haveEnv = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Environment &QtcProcess::environment() const
|
const Environment &QtcProcess::environment() const
|
||||||
{
|
{
|
||||||
return d->m_setup.m_environment;
|
return d->m_setup->m_environment;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QtcProcess::hasEnvironment() const
|
bool QtcProcess::hasEnvironment() const
|
||||||
{
|
{
|
||||||
return d->m_setup.m_haveEnv;
|
return d->m_setup->m_haveEnv;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtcProcess::setRemoteEnvironment(const Environment &environment)
|
void QtcProcess::setRemoteEnvironment(const Environment &environment)
|
||||||
{
|
{
|
||||||
d->m_setup.m_remoteEnvironment = environment;
|
d->m_setup->m_remoteEnvironment = environment;
|
||||||
}
|
}
|
||||||
|
|
||||||
Environment QtcProcess::remoteEnvironment() const
|
Environment QtcProcess::remoteEnvironment() const
|
||||||
{
|
{
|
||||||
return d->m_setup.m_remoteEnvironment;
|
return d->m_setup->m_remoteEnvironment;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtcProcess::setCommand(const CommandLine &cmdLine)
|
void QtcProcess::setCommand(const CommandLine &cmdLine)
|
||||||
{
|
{
|
||||||
if (d->m_setup.m_workingDirectory.needsDevice() && cmdLine.executable().needsDevice()) {
|
if (d->m_setup->m_workingDirectory.needsDevice() && cmdLine.executable().needsDevice()) {
|
||||||
QTC_CHECK(d->m_setup.m_workingDirectory.host() == cmdLine.executable().host());
|
QTC_CHECK(d->m_setup->m_workingDirectory.host() == cmdLine.executable().host());
|
||||||
}
|
}
|
||||||
d->m_setup.m_commandLine = cmdLine;
|
d->m_setup->m_commandLine = cmdLine;
|
||||||
}
|
}
|
||||||
|
|
||||||
const CommandLine &QtcProcess::commandLine() const
|
const CommandLine &QtcProcess::commandLine() const
|
||||||
{
|
{
|
||||||
return d->m_setup.m_commandLine;
|
return d->m_setup->m_commandLine;
|
||||||
}
|
}
|
||||||
|
|
||||||
FilePath QtcProcess::workingDirectory() const
|
FilePath QtcProcess::workingDirectory() const
|
||||||
{
|
{
|
||||||
return d->m_setup.m_workingDirectory;
|
return d->m_setup->m_workingDirectory;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtcProcess::setWorkingDirectory(const FilePath &dir)
|
void QtcProcess::setWorkingDirectory(const FilePath &dir)
|
||||||
{
|
{
|
||||||
if (dir.needsDevice() && d->m_setup.m_commandLine.executable().needsDevice()) {
|
if (dir.needsDevice() && d->m_setup->m_commandLine.executable().needsDevice()) {
|
||||||
QTC_CHECK(dir.host() == d->m_setup.m_commandLine.executable().host());
|
QTC_CHECK(dir.host() == d->m_setup->m_commandLine.executable().host());
|
||||||
}
|
}
|
||||||
d->m_setup.m_workingDirectory = dir;
|
d->m_setup->m_workingDirectory = dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtcProcess::setUseCtrlCStub(bool enabled)
|
void QtcProcess::setUseCtrlCStub(bool enabled)
|
||||||
@@ -862,7 +863,7 @@ void QtcProcess::setUseCtrlCStub(bool enabled)
|
|||||||
// Qt Creator otherwise, because they share the same Windows console.
|
// Qt Creator otherwise, because they share the same Windows console.
|
||||||
// See QTCREATORBUG-11995 for details.
|
// See QTCREATORBUG-11995 for details.
|
||||||
#ifndef QT_DEBUG
|
#ifndef QT_DEBUG
|
||||||
d->m_setup.m_useCtrlCStub = enabled;
|
d->m_setup->m_useCtrlCStub = enabled;
|
||||||
#else
|
#else
|
||||||
Q_UNUSED(enabled)
|
Q_UNUSED(enabled)
|
||||||
#endif
|
#endif
|
||||||
@@ -874,7 +875,7 @@ void QtcProcess::start()
|
|||||||
// QTC_ASSERT(state() == QProcess::NotRunning, return);
|
// QTC_ASSERT(state() == QProcess::NotRunning, return);
|
||||||
|
|
||||||
ProcessInterface *processImpl = nullptr;
|
ProcessInterface *processImpl = nullptr;
|
||||||
if (d->m_setup.m_commandLine.executable().needsDevice()) {
|
if (d->m_setup->m_commandLine.executable().needsDevice()) {
|
||||||
if (s_deviceHooks.processImplHook) { // TODO: replace "if" with an assert for the hook
|
if (s_deviceHooks.processImplHook) { // TODO: replace "if" with an assert for the hook
|
||||||
processImpl = s_deviceHooks.processImplHook(commandLine().executable());
|
processImpl = s_deviceHooks.processImplHook(commandLine().executable());
|
||||||
}
|
}
|
||||||
@@ -889,8 +890,8 @@ void QtcProcess::start()
|
|||||||
QTC_ASSERT(processImpl, return);
|
QTC_ASSERT(processImpl, return);
|
||||||
setProcessInterface(processImpl);
|
setProcessInterface(processImpl);
|
||||||
d->clearForRun();
|
d->clearForRun();
|
||||||
d->m_process->m_setup.m_commandLine = d->fullCommandLine();
|
d->m_process->m_setup->m_commandLine = d->fullCommandLine();
|
||||||
d->m_process->m_setup.m_environment = d->fullEnvironment();
|
d->m_process->m_setup->m_environment = d->fullEnvironment();
|
||||||
if (processLog().isDebugEnabled()) {
|
if (processLog().isDebugEnabled()) {
|
||||||
// Pass a dynamic property with info about blocking type
|
// Pass a dynamic property with info about blocking type
|
||||||
d->m_process->setProperty(QTC_PROCESS_BLOCKING_TYPE, property(QTC_PROCESS_BLOCKING_TYPE));
|
d->m_process->setProperty(QTC_PROCESS_BLOCKING_TYPE, property(QTC_PROCESS_BLOCKING_TYPE));
|
||||||
@@ -926,7 +927,7 @@ BOOL CALLBACK sendInterruptMessageToAllWindowsOfProcess_enumWnd(HWND hwnd, LPARA
|
|||||||
void QtcProcess::terminate()
|
void QtcProcess::terminate()
|
||||||
{
|
{
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
if (d->m_setup.m_useCtrlCStub)
|
if (d->m_setup->m_useCtrlCStub)
|
||||||
EnumWindows(sendShutDownMessageToAllWindowsOfProcess_enumWnd, processId());
|
EnumWindows(sendShutDownMessageToAllWindowsOfProcess_enumWnd, processId());
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
@@ -937,7 +938,7 @@ void QtcProcess::terminate()
|
|||||||
void QtcProcess::interrupt()
|
void QtcProcess::interrupt()
|
||||||
{
|
{
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
QTC_ASSERT(d->m_setup.m_useCtrlCStub, return);
|
QTC_ASSERT(d->m_setup->m_useCtrlCStub, return);
|
||||||
EnumWindows(sendInterruptMessageToAllWindowsOfProcess_enumWnd, processId());
|
EnumWindows(sendInterruptMessageToAllWindowsOfProcess_enumWnd, processId());
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -952,71 +953,71 @@ bool QtcProcess::startDetached(const CommandLine &cmd, const FilePath &workingDi
|
|||||||
|
|
||||||
void QtcProcess::setLowPriority()
|
void QtcProcess::setLowPriority()
|
||||||
{
|
{
|
||||||
d->m_setup.m_lowPriority = true;
|
d->m_setup->m_lowPriority = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtcProcess::setDisableUnixTerminal()
|
void QtcProcess::setDisableUnixTerminal()
|
||||||
{
|
{
|
||||||
d->m_setup.m_unixTerminalDisabled = true;
|
d->m_setup->m_unixTerminalDisabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtcProcess::setAbortOnMetaChars(bool abort)
|
void QtcProcess::setAbortOnMetaChars(bool abort)
|
||||||
{
|
{
|
||||||
d->m_setup.m_abortOnMetaChars = abort;
|
d->m_setup->m_abortOnMetaChars = abort;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtcProcess::setRunAsRoot(bool on)
|
void QtcProcess::setRunAsRoot(bool on)
|
||||||
{
|
{
|
||||||
d->m_setup.m_runAsRoot = on;
|
d->m_setup->m_runAsRoot = on;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QtcProcess::isRunAsRoot() const
|
bool QtcProcess::isRunAsRoot() const
|
||||||
{
|
{
|
||||||
return d->m_setup.m_runAsRoot;
|
return d->m_setup->m_runAsRoot;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtcProcess::setStandardInputFile(const QString &inputFile)
|
void QtcProcess::setStandardInputFile(const QString &inputFile)
|
||||||
{
|
{
|
||||||
d->m_setup.m_standardInputFile = inputFile;
|
d->m_setup->m_standardInputFile = inputFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString QtcProcess::toStandaloneCommandLine() const
|
QString QtcProcess::toStandaloneCommandLine() const
|
||||||
{
|
{
|
||||||
QStringList parts;
|
QStringList parts;
|
||||||
parts.append("/usr/bin/env");
|
parts.append("/usr/bin/env");
|
||||||
if (!d->m_setup.m_workingDirectory.isEmpty()) {
|
if (!d->m_setup->m_workingDirectory.isEmpty()) {
|
||||||
parts.append("-C");
|
parts.append("-C");
|
||||||
d->m_setup.m_workingDirectory.path();
|
d->m_setup->m_workingDirectory.path();
|
||||||
}
|
}
|
||||||
parts.append("-i");
|
parts.append("-i");
|
||||||
if (d->m_setup.m_environment.size() > 0) {
|
if (d->m_setup->m_environment.size() > 0) {
|
||||||
const QStringList envVars = d->m_setup.m_environment.toStringList();
|
const QStringList envVars = d->m_setup->m_environment.toStringList();
|
||||||
std::transform(envVars.cbegin(), envVars.cend(),
|
std::transform(envVars.cbegin(), envVars.cend(),
|
||||||
std::back_inserter(parts), ProcessArgs::quoteArgUnix);
|
std::back_inserter(parts), ProcessArgs::quoteArgUnix);
|
||||||
}
|
}
|
||||||
parts.append(d->m_setup.m_commandLine.executable().path());
|
parts.append(d->m_setup->m_commandLine.executable().path());
|
||||||
parts.append(d->m_setup.m_commandLine.splitArguments());
|
parts.append(d->m_setup->m_commandLine.splitArguments());
|
||||||
return parts.join(" ");
|
return parts.join(" ");
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtcProcess::setExtraData(const QString &key, const QVariant &value)
|
void QtcProcess::setExtraData(const QString &key, const QVariant &value)
|
||||||
{
|
{
|
||||||
d->m_setup.m_extraData.insert(key, value);
|
d->m_setup->m_extraData.insert(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant QtcProcess::extraData(const QString &key) const
|
QVariant QtcProcess::extraData(const QString &key) const
|
||||||
{
|
{
|
||||||
return d->m_setup.m_extraData.value(key);
|
return d->m_setup->m_extraData.value(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtcProcess::setExtraData(const QVariantHash &extraData)
|
void QtcProcess::setExtraData(const QVariantHash &extraData)
|
||||||
{
|
{
|
||||||
d->m_setup.m_extraData = extraData;
|
d->m_setup->m_extraData = extraData;
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariantHash QtcProcess::extraData() const
|
QVariantHash QtcProcess::extraData() const
|
||||||
{
|
{
|
||||||
return d->m_setup.m_extraData;
|
return d->m_setup->m_extraData;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtcProcess::setRemoteProcessHooks(const DeviceProcessHooks &hooks)
|
void QtcProcess::setRemoteProcessHooks(const DeviceProcessHooks &hooks)
|
||||||
@@ -1101,7 +1102,7 @@ bool QtcProcess::readDataFromProcess(int timeoutS,
|
|||||||
}
|
}
|
||||||
// Prompt user, pretend we have data if says 'No'.
|
// Prompt user, pretend we have data if says 'No'.
|
||||||
const bool hang = !hasData && !finished;
|
const bool hang = !hasData && !finished;
|
||||||
hasData = hang && showTimeOutMessageBox && !askToKill(d->m_setup.m_commandLine.executable().path());
|
hasData = hang && showTimeOutMessageBox && !askToKill(d->m_setup->m_commandLine.executable().path());
|
||||||
} while (hasData && !finished);
|
} while (hasData && !finished);
|
||||||
if (syncDebug)
|
if (syncDebug)
|
||||||
qDebug() << "<readDataFromProcess" << finished;
|
qDebug() << "<readDataFromProcess" << finished;
|
||||||
@@ -1249,7 +1250,7 @@ qint64 QtcProcess::applicationMainThreadID() const
|
|||||||
|
|
||||||
void QtcProcess::setProcessChannelMode(QProcess::ProcessChannelMode mode)
|
void QtcProcess::setProcessChannelMode(QProcess::ProcessChannelMode mode)
|
||||||
{
|
{
|
||||||
d->m_setup.m_processChannelMode = mode;
|
d->m_setup->m_processChannelMode = mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
QProcess::ProcessError QtcProcess::error() const
|
QProcess::ProcessError QtcProcess::error() const
|
||||||
@@ -1277,7 +1278,7 @@ QString QtcProcess::errorString() const
|
|||||||
{
|
{
|
||||||
if (d->m_process)
|
if (d->m_process)
|
||||||
return d->m_process->errorString();
|
return d->m_process->errorString();
|
||||||
return d->m_setup.m_errorString;
|
return d->m_setup->m_errorString;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtcProcess::setErrorString(const QString &str)
|
void QtcProcess::setErrorString(const QString &str)
|
||||||
@@ -1285,7 +1286,7 @@ void QtcProcess::setErrorString(const QString &str)
|
|||||||
if (d->m_process)
|
if (d->m_process)
|
||||||
d->m_process->setErrorString(str);
|
d->m_process->setErrorString(str);
|
||||||
else
|
else
|
||||||
d->m_setup.m_errorString = str;
|
d->m_setup->m_errorString = str;
|
||||||
}
|
}
|
||||||
|
|
||||||
qint64 QtcProcess::processId() const
|
qint64 QtcProcess::processId() const
|
||||||
@@ -1585,7 +1586,7 @@ void QtcProcess::setExitCodeInterpreter(const ExitCodeInterpreter &interpreter)
|
|||||||
|
|
||||||
void QtcProcess::setWriteData(const QByteArray &writeData)
|
void QtcProcess::setWriteData(const QByteArray &writeData)
|
||||||
{
|
{
|
||||||
d->m_setup.m_writeData = writeData;
|
d->m_setup->m_writeData = writeData;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef QT_GUI_LIB
|
#ifdef QT_GUI_LIB
|
||||||
@@ -1599,7 +1600,7 @@ void QtcProcess::runBlocking(EventLoopMode eventLoopMode)
|
|||||||
{
|
{
|
||||||
// FIXME: Implement properly
|
// FIXME: Implement properly
|
||||||
|
|
||||||
if (d->m_setup.m_commandLine.executable().needsDevice()) {
|
if (d->m_setup->m_commandLine.executable().needsDevice()) {
|
||||||
QtcProcess::start();
|
QtcProcess::start();
|
||||||
waitForFinished();
|
waitForFinished();
|
||||||
return;
|
return;
|
||||||
@@ -1697,7 +1698,7 @@ void QtcProcessPrivate::slotTimeout()
|
|||||||
qDebug() << Q_FUNC_INFO << "HANG detected, killing";
|
qDebug() << Q_FUNC_INFO << "HANG detected, killing";
|
||||||
m_waitingForUser = true;
|
m_waitingForUser = true;
|
||||||
const bool terminate = !m_timeOutMessageBoxEnabled
|
const bool terminate = !m_timeOutMessageBoxEnabled
|
||||||
|| askToKill(m_setup.m_commandLine.executable().toString());
|
|| askToKill(m_setup->m_commandLine.executable().toString());
|
||||||
m_waitingForUser = false;
|
m_waitingForUser = false;
|
||||||
if (terminate) {
|
if (terminate) {
|
||||||
q->stopProcess();
|
q->stopProcess();
|
||||||
|
Reference in New Issue
Block a user