forked from qt-creator/qt-creator
RemoteLinux: Allow killing processes by ID
Killing every process on the system that happens to have the same name as the one we've started is error prone and dangerous. We might kill processes we haven't started and other processes might rename themselves at runtime so that we don't find them anymore. The process ID is obtained by outputting it as very first thing on stdout and then starting the process with "exec", so that it isn't forked. Change-Id: Icc51bd1968afc47f4dc42f9e90e5dcbd0b1e40a7 Reviewed-by: Tobias Hunger <tobias.hunger@qt.io> Reviewed-by: Christian Kandeler <christian.kandeler@theqtcompany.com>
This commit is contained in:
@@ -172,6 +172,11 @@ void SshDeviceProcess::setSshServerSupportsSignals(bool signalsSupported)
|
|||||||
d->serverSupportsSignals = signalsSupported;
|
d->serverSupportsSignals = signalsSupported;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qint64 SshDeviceProcess::processId() const
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void SshDeviceProcess::handleConnected()
|
void SshDeviceProcess::handleConnected()
|
||||||
{
|
{
|
||||||
QTC_ASSERT(d->state == SshDeviceProcessPrivate::Connecting, return);
|
QTC_ASSERT(d->state == SshDeviceProcessPrivate::Connecting, return);
|
||||||
@@ -303,7 +308,11 @@ void SshDeviceProcess::SshDeviceProcessPrivate::doSignal(QSsh::SshRemoteProcess:
|
|||||||
process->sendSignal(signal);
|
process->sendSignal(signal);
|
||||||
} else {
|
} else {
|
||||||
DeviceProcessSignalOperation::Ptr signalOperation = q->device()->signalOperation();
|
DeviceProcessSignalOperation::Ptr signalOperation = q->device()->signalOperation();
|
||||||
|
quint64 processId = q->processId();
|
||||||
if (signal == QSsh::SshRemoteProcess::IntSignal) {
|
if (signal == QSsh::SshRemoteProcess::IntSignal) {
|
||||||
|
if (processId != 0)
|
||||||
|
signalOperation->interruptProcess(processId);
|
||||||
|
else
|
||||||
signalOperation->interruptProcess(runnable.executable);
|
signalOperation->interruptProcess(runnable.executable);
|
||||||
} else {
|
} else {
|
||||||
if (killOperation) // We are already in the process of killing the app.
|
if (killOperation) // We are already in the process of killing the app.
|
||||||
@@ -312,6 +321,9 @@ void SshDeviceProcess::SshDeviceProcessPrivate::doSignal(QSsh::SshRemoteProcess:
|
|||||||
connect(signalOperation.data(), &DeviceProcessSignalOperation::finished, q,
|
connect(signalOperation.data(), &DeviceProcessSignalOperation::finished, q,
|
||||||
&SshDeviceProcess::handleKillOperationFinished);
|
&SshDeviceProcess::handleKillOperationFinished);
|
||||||
killTimer.start(5000);
|
killTimer.start(5000);
|
||||||
|
if (processId != 0)
|
||||||
|
signalOperation->killProcess(processId);
|
||||||
|
else
|
||||||
signalOperation->killProcess(runnable.executable);
|
signalOperation->killProcess(runnable.executable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -68,6 +68,7 @@ private:
|
|||||||
void handleKillOperationTimeout();
|
void handleKillOperationTimeout();
|
||||||
|
|
||||||
virtual QString fullCommandLine(const StandardRunnable &runnable) const;
|
virtual QString fullCommandLine(const StandardRunnable &runnable) const;
|
||||||
|
virtual qint64 processId() const;
|
||||||
|
|
||||||
class SshDeviceProcessPrivate;
|
class SshDeviceProcessPrivate;
|
||||||
friend class SshDeviceProcessPrivate;
|
friend class SshDeviceProcessPrivate;
|
||||||
|
@@ -39,8 +39,11 @@ static QString quote(const QString &s) { return Utils::QtcProcess::quoteArgUnix(
|
|||||||
|
|
||||||
LinuxDeviceProcess::LinuxDeviceProcess(const QSharedPointer<const ProjectExplorer::IDevice> &device,
|
LinuxDeviceProcess::LinuxDeviceProcess(const QSharedPointer<const ProjectExplorer::IDevice> &device,
|
||||||
QObject *parent)
|
QObject *parent)
|
||||||
: ProjectExplorer::SshDeviceProcess(device, parent)
|
: ProjectExplorer::SshDeviceProcess(device, parent), m_processId(0)
|
||||||
{
|
{
|
||||||
|
connect(this, &DeviceProcess::finished, this, [this]() {
|
||||||
|
m_processId = 0;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void LinuxDeviceProcess::setRcFilesToSource(const QStringList &filePaths)
|
void LinuxDeviceProcess::setRcFilesToSource(const QStringList &filePaths)
|
||||||
@@ -48,6 +51,28 @@ void LinuxDeviceProcess::setRcFilesToSource(const QStringList &filePaths)
|
|||||||
m_rcFilesToSource = filePaths;
|
m_rcFilesToSource = filePaths;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QByteArray LinuxDeviceProcess::readAllStandardOutput()
|
||||||
|
{
|
||||||
|
QByteArray output = SshDeviceProcess::readAllStandardOutput();
|
||||||
|
if (m_processId != 0)
|
||||||
|
return output;
|
||||||
|
|
||||||
|
m_processIdString.append(output);
|
||||||
|
int cut = m_processIdString.indexOf('\n');
|
||||||
|
if (cut != -1) {
|
||||||
|
m_processId = m_processIdString.left(cut).toLongLong();
|
||||||
|
output = m_processIdString.mid(cut + 1);
|
||||||
|
m_processIdString.clear();
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
return QByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
qint64 LinuxDeviceProcess::processId() const
|
||||||
|
{
|
||||||
|
return m_processId;
|
||||||
|
}
|
||||||
|
|
||||||
QString LinuxDeviceProcess::fullCommandLine(const StandardRunnable &runnable) const
|
QString LinuxDeviceProcess::fullCommandLine(const StandardRunnable &runnable) const
|
||||||
{
|
{
|
||||||
const Environment env = runnable.environment;
|
const Environment env = runnable.environment;
|
||||||
@@ -66,10 +91,10 @@ QString LinuxDeviceProcess::fullCommandLine(const StandardRunnable &runnable) co
|
|||||||
envString.append(it.key()).append(QLatin1String("='")).append(it.value())
|
envString.append(it.key()).append(QLatin1String("='")).append(it.value())
|
||||||
.append(QLatin1Char('\''));
|
.append(QLatin1Char('\''));
|
||||||
}
|
}
|
||||||
|
fullCommandLine.append("echo $$ && ");
|
||||||
if (!envString.isEmpty())
|
if (!envString.isEmpty())
|
||||||
fullCommandLine.append(QLatin1Char(' ')).append(envString);
|
fullCommandLine.append(envString);
|
||||||
if (!fullCommandLine.isEmpty())
|
fullCommandLine.append(" exec ");
|
||||||
fullCommandLine += QLatin1Char(' ');
|
|
||||||
fullCommandLine.append(quote(runnable.executable));
|
fullCommandLine.append(quote(runnable.executable));
|
||||||
if (!runnable.commandLineArguments.isEmpty()) {
|
if (!runnable.commandLineArguments.isEmpty()) {
|
||||||
fullCommandLine.append(QLatin1Char(' '));
|
fullCommandLine.append(QLatin1Char(' '));
|
||||||
|
@@ -43,12 +43,17 @@ public:
|
|||||||
// Files to source before executing the command (if they exist). Overrides the default.
|
// Files to source before executing the command (if they exist). Overrides the default.
|
||||||
void setRcFilesToSource(const QStringList &filePaths);
|
void setRcFilesToSource(const QStringList &filePaths);
|
||||||
|
|
||||||
|
QByteArray readAllStandardOutput() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString fullCommandLine(const ProjectExplorer::StandardRunnable &) const override;
|
QString fullCommandLine(const ProjectExplorer::StandardRunnable &) const override;
|
||||||
|
qint64 processId() const override;
|
||||||
|
|
||||||
QStringList rcFilesToSource() const;
|
QStringList rcFilesToSource() const;
|
||||||
|
|
||||||
QStringList m_rcFilesToSource;
|
QStringList m_rcFilesToSource;
|
||||||
|
QByteArray m_processIdString;
|
||||||
|
qint64 m_processId;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace RemoteLinux
|
} // namespace RemoteLinux
|
||||||
|
Reference in New Issue
Block a user