diff --git a/src/libs/utils/launcherpackets.cpp b/src/libs/utils/launcherpackets.cpp index ee68a70b144..87a3656306a 100644 --- a/src/libs/utils/launcherpackets.cpp +++ b/src/libs/utils/launcherpackets.cpp @@ -69,7 +69,8 @@ void StartProcessPacket::doSerialize(QDataStream &stream) const << nativeArguments << lowPriority << unixTerminalDisabled - << useCtrlCStub; + << useCtrlCStub + << reaperTimeout; } void StartProcessPacket::doDeserialize(QDataStream &stream) @@ -88,7 +89,8 @@ void StartProcessPacket::doDeserialize(QDataStream &stream) >> nativeArguments >> lowPriority >> unixTerminalDisabled - >> useCtrlCStub; + >> useCtrlCStub + >> reaperTimeout; processMode = Utils::ProcessMode(processModeInt); processChannelMode = QProcess::ProcessChannelMode(processChannelModeInt); } diff --git a/src/libs/utils/launcherpackets.h b/src/libs/utils/launcherpackets.h index 2c4dad8d08b..066862ef796 100644 --- a/src/libs/utils/launcherpackets.h +++ b/src/libs/utils/launcherpackets.h @@ -119,6 +119,7 @@ public: bool lowPriority = false; bool unixTerminalDisabled = false; bool useCtrlCStub = false; + int reaperTimeout = 500; private: void doSerialize(QDataStream &stream) const override; diff --git a/src/libs/utils/launchersocket.cpp b/src/libs/utils/launchersocket.cpp index 1677fd892cc..fc8ea36042f 100644 --- a/src/libs/utils/launchersocket.cpp +++ b/src/libs/utils/launchersocket.cpp @@ -288,6 +288,7 @@ void CallerHandle::start(const QString &program, const QStringList &arguments) p.lowPriority = m_setup->m_lowPriority; p.unixTerminalDisabled = m_setup->m_unixTerminalDisabled; p.useCtrlCStub = m_setup->m_useCtrlCStub; + p.reaperTimeout = m_setup->m_reaperTimeout; sendPacket(p); } diff --git a/src/libs/utils/processinterface.h b/src/libs/utils/processinterface.h index 0295f92d0c1..1722a2c6849 100644 --- a/src/libs/utils/processinterface.h +++ b/src/libs/utils/processinterface.h @@ -54,6 +54,7 @@ public: QString m_standardInputFile; QString m_nativeArguments; // internal, dependent on specific code path + int m_reaperTimeout = 500; // in ms bool m_abortOnMetaChars = true; bool m_runAsRoot = false; bool m_lowPriority = false; diff --git a/src/libs/utils/qtcprocess.cpp b/src/libs/utils/qtcprocess.cpp index 69cf99325bc..b8272f64ce5 100644 --- a/src/libs/utils/qtcprocess.cpp +++ b/src/libs/utils/qtcprocess.cpp @@ -340,7 +340,7 @@ public: emit readyRead({}, m_process->readAllStandardError()); }); } - ~QProcessImpl() final { ProcessReaper::reap(m_process); } + ~QProcessImpl() final { ProcessReaper::reap(m_process, m_setup.m_reaperTimeout); } private: qint64 write(const QByteArray &data) final { return m_process->write(data); } @@ -1166,6 +1166,16 @@ QVariantHash QtcProcess::extraData() const return d->m_setup.m_extraData; } +void QtcProcess::setReaperTimeout(int msecs) +{ + d->m_setup.m_reaperTimeout = msecs; +} + +int QtcProcess::reaperTimeout() const +{ + return d->m_setup.m_reaperTimeout; +} + void QtcProcess::setRemoteProcessHooks(const DeviceProcessHooks &hooks) { s_deviceHooks = hooks; @@ -1501,12 +1511,16 @@ void QtcProcess::close() d->clearForRun(); } -void QtcProcess::stop(int killTimeout) +/* + Calls terminate() directly and after a delay of reaperTimeout() it calls kill() + if the process is still running. +*/ +void QtcProcess::stop() { if (state() == QProcess::NotRunning) return; - d->sendControlSignal(ControlSignal::Terminate, killTimeout); + d->sendControlSignal(ControlSignal::Terminate, d->m_process->m_setup.m_reaperTimeout); } QString QtcProcess::locateBinary(const QString &binary) diff --git a/src/libs/utils/qtcprocess.h b/src/libs/utils/qtcprocess.h index 7d2f39b1deb..15cc4693c3c 100644 --- a/src/libs/utils/qtcprocess.h +++ b/src/libs/utils/qtcprocess.h @@ -65,7 +65,7 @@ public: void interrupt(); void kickoffProcess(); void close(); - void stop(int killTimeout = 500); + void stop(); QByteArray readAllStandardOutput(); QByteArray readAllStandardError(); @@ -131,6 +131,9 @@ public: void setExtraData(const QVariantHash &extraData); QVariantHash extraData() const; + void setReaperTimeout(int msecs); + int reaperTimeout() const; + static void setRemoteProcessHooks(const DeviceProcessHooks &hooks); // TODO: Some usages of this method assume that Starting phase is also a running state diff --git a/src/libs/utils/terminalprocess.cpp b/src/libs/utils/terminalprocess.cpp index 8a37aeec5b0..a623191524d 100644 --- a/src/libs/utils/terminalprocess.cpp +++ b/src/libs/utils/terminalprocess.cpp @@ -411,6 +411,7 @@ void TerminalImpl::start() d->m_process.setEnvironment(m_setup.m_environment); d->m_process.setCommand({FilePath::fromString(terminal.command), allArgs}); d->m_process.setProcessImpl(m_setup.m_processImpl); + d->m_process.setReaperTimeout(m_setup.m_reaperTimeout); d->m_process.start(); if (!d->m_process.waitForStarted()) { const QString msg = tr("Cannot start the terminal emulator \"%1\", change the setting in the " diff --git a/src/plugins/docker/dockerdevice.cpp b/src/plugins/docker/dockerdevice.cpp index 285b2f4cf6f..822007253ae 100644 --- a/src/plugins/docker/dockerdevice.cpp +++ b/src/plugins/docker/dockerdevice.cpp @@ -264,6 +264,7 @@ void DockerProcessImpl::start() m_process.setProcessImpl(m_setup.m_processImpl); m_process.setProcessMode(m_setup.m_processMode); m_process.setTerminalMode(m_setup.m_terminalMode); + m_process.setReaperTimeout(m_setup.m_reaperTimeout); m_process.setWriteData(m_setup.m_writeData); m_process.setProcessChannelMode(m_setup.m_processChannelMode); m_process.setExtraData(m_setup.m_extraData); diff --git a/src/plugins/remotelinux/linuxdevice.cpp b/src/plugins/remotelinux/linuxdevice.cpp index 93b93ca416f..7f6dbb44586 100644 --- a/src/plugins/remotelinux/linuxdevice.cpp +++ b/src/plugins/remotelinux/linuxdevice.cpp @@ -738,6 +738,7 @@ void SshProcessInterfacePrivate::doStart() m_process.setProcessImpl(q->m_setup.m_processImpl); m_process.setProcessMode(q->m_setup.m_processMode); m_process.setTerminalMode(q->m_setup.m_terminalMode); + m_process.setReaperTimeout(q->m_setup.m_reaperTimeout); m_process.setWriteData(q->m_setup.m_writeData); // TODO: what about other fields from m_setup? SshParameters::setupSshEnvironment(&m_process); diff --git a/src/tools/processlauncher/launchersockethandler.cpp b/src/tools/processlauncher/launchersockethandler.cpp index 321f4688195..03ddb6528ff 100644 --- a/src/tools/processlauncher/launchersockethandler.cpp +++ b/src/tools/processlauncher/launchersockethandler.cpp @@ -44,9 +44,12 @@ public: ProcessHelper(parent), m_token(token) { } quintptr token() const { return m_token; } + void setReaperTimeout(int msecs) { m_reaperTimeout = msecs; }; + int reaperTimeout() const { return m_reaperTimeout; } private: const quintptr m_token; + int m_reaperTimeout = 500; }; LauncherSocketHandler::LauncherSocketHandler(QString serverPath, QObject *parent) @@ -208,6 +211,7 @@ void LauncherSocketHandler::handleStartPacket() if (packet.unixTerminalDisabled) process->setUnixTerminalDisabled(); process->setUseCtrlCStub(packet.useCtrlCStub); + process->setReaperTimeout(packet.reaperTimeout); process->start(packet.command, packet.arguments, handler->openMode()); handler->handleProcessStart(); } @@ -289,7 +293,7 @@ void LauncherSocketHandler::removeProcess(quintptr token) Process *process = it.value(); m_processes.erase(it); - ProcessReaper::reap(process); + ProcessReaper::reap(process, process->reaperTimeout()); } } // namespace Internal