forked from qt-creator/qt-creator
Device support: Introduce IDevice helper classes.
These are for configuration of process and ports gathering activities, respectively. This couples related functionality more tightly, while keeping the number of IDevice methods at a reasonable level. For ports gathering, the patch also adds the ability to configure both the command and the parsing function; the latter used to be hardcoded in the PortsGatherer class. Change-Id: I1b8940397a51efa7ddc05dd15cf861777d118c1a Reviewed-by: hjk <qthjk@ovi.com>
This commit is contained in:
@@ -90,22 +90,5 @@ IDevice::Ptr AndroidDevice::clone() const
|
||||
return IDevice::Ptr(new AndroidDevice(*this));
|
||||
}
|
||||
|
||||
QString AndroidDevice::listProcessesCommandLine() const
|
||||
{
|
||||
return QString();
|
||||
}
|
||||
|
||||
QString AndroidDevice::killProcessCommandLine(const DeviceProcess &process) const
|
||||
{
|
||||
Q_UNUSED(process);
|
||||
return QString();
|
||||
}
|
||||
|
||||
QList<DeviceProcess> AndroidDevice::buildProcessList(const QString &listProcessesReply) const
|
||||
{
|
||||
Q_UNUSED(listProcessesReply);
|
||||
return QList<DeviceProcess>();
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Android
|
||||
|
||||
@@ -51,10 +51,6 @@ public:
|
||||
|
||||
ProjectExplorer::IDevice::Ptr clone() const;
|
||||
|
||||
QString listProcessesCommandLine() const;
|
||||
QString killProcessCommandLine(const ProjectExplorer::DeviceProcess &process) const;
|
||||
QList<ProjectExplorer::DeviceProcess> buildProcessList(const QString &listProcessesReply) const;
|
||||
|
||||
protected:
|
||||
friend class AndroidDeviceFactory;
|
||||
friend class Android::AndroidPlugin;
|
||||
|
||||
@@ -85,21 +85,4 @@ IDevice::Ptr DesktopDevice::clone() const
|
||||
return Ptr(new DesktopDevice(*this));
|
||||
}
|
||||
|
||||
QString DesktopDevice::listProcessesCommandLine() const
|
||||
{
|
||||
return QString();
|
||||
}
|
||||
|
||||
QString DesktopDevice::killProcessCommandLine(const DeviceProcess &process) const
|
||||
{
|
||||
Q_UNUSED(process);
|
||||
return QString();
|
||||
}
|
||||
|
||||
QList<DeviceProcess> DesktopDevice::buildProcessList(const QString &listProcessesReply) const
|
||||
{
|
||||
Q_UNUSED(listProcessesReply);
|
||||
return QList<DeviceProcess>();
|
||||
}
|
||||
|
||||
} // namespace ProjectExplorer
|
||||
|
||||
@@ -54,10 +54,6 @@ public:
|
||||
|
||||
IDevice::Ptr clone() const;
|
||||
|
||||
QString listProcessesCommandLine() const;
|
||||
QString killProcessCommandLine(const DeviceProcess &process) const;
|
||||
QList<DeviceProcess> buildProcessList(const QString &listProcessesReply) const;
|
||||
|
||||
protected:
|
||||
DesktopDevice();
|
||||
DesktopDevice(const DesktopDevice &other);
|
||||
|
||||
@@ -71,6 +71,7 @@ DeviceProcessList::~DeviceProcessList()
|
||||
void DeviceProcessList::update()
|
||||
{
|
||||
QTC_ASSERT(d->state == Inactive, return);
|
||||
QTC_ASSERT(d->device && d->device->processSupport(), return);
|
||||
|
||||
if (!d->remoteProcesses.isEmpty()) {
|
||||
beginRemoveRows(QModelIndex(), 0, d->remoteProcesses.count() - 1);
|
||||
@@ -78,7 +79,7 @@ void DeviceProcessList::update()
|
||||
endRemoveRows();
|
||||
}
|
||||
d->state = Listing;
|
||||
startProcess(d->device->listProcessesCommandLine());
|
||||
startProcess(d->device->processSupport()->listProcessesCommandLine());
|
||||
}
|
||||
|
||||
void DeviceProcessList::killProcess(int row)
|
||||
@@ -87,7 +88,8 @@ void DeviceProcessList::killProcess(int row)
|
||||
QTC_ASSERT(d->state == Inactive, return);
|
||||
|
||||
d->state = Killing;
|
||||
startProcess(d->device->killProcessCommandLine(d->remoteProcesses.at(row)));
|
||||
const int pid = d->remoteProcesses.at(row).pid;
|
||||
startProcess(d->device->processSupport()->killProcessByPidCommandLine(pid));
|
||||
}
|
||||
|
||||
DeviceProcess DeviceProcessList::at(int row) const
|
||||
@@ -160,8 +162,10 @@ void DeviceProcessList::handleRemoteProcessFinished(int exitStatus)
|
||||
if (d->process.processExitCode() == 0) {
|
||||
if (d->state == Listing) {
|
||||
const QByteArray remoteStdout = d->process.readAllStandardOutput();
|
||||
QList<DeviceProcess> processes = d->device->buildProcessList(QString::fromUtf8(remoteStdout.data(),
|
||||
remoteStdout.count()));
|
||||
const QString stdoutString
|
||||
= QString::fromUtf8(remoteStdout.data(), remoteStdout.count());
|
||||
QList<DeviceProcess> processes
|
||||
= d->device->processSupport()->buildProcessList(stdoutString);
|
||||
if (!processes.isEmpty()) {
|
||||
beginInsertRows(QModelIndex(), 0, processes.count()-1);
|
||||
d->remoteProcesses = processes;
|
||||
|
||||
@@ -46,11 +46,10 @@ class DeviceUsedPortsGathererPrivate
|
||||
public:
|
||||
SshConnection *connection;
|
||||
SshRemoteProcess::Ptr process;
|
||||
PortList portsToCheck;
|
||||
QList<int> usedPorts;
|
||||
QByteArray remoteStdout;
|
||||
QByteArray remoteStderr;
|
||||
QString command;
|
||||
IDevice::ConstPtr device;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
@@ -70,7 +69,9 @@ DeviceUsedPortsGatherer::~DeviceUsedPortsGatherer()
|
||||
void DeviceUsedPortsGatherer::start(const IDevice::ConstPtr &device)
|
||||
{
|
||||
QTC_ASSERT(!d->connection, return);
|
||||
d->portsToCheck = device->freePorts();
|
||||
QTC_ASSERT(device && device->portsGatheringMethod(), return);
|
||||
|
||||
d->device = device;
|
||||
d->connection = SshConnectionManager::instance().acquireConnection(device->sshParameters());
|
||||
connect(d->connection, SIGNAL(error(QSsh::SshError)), SLOT(handleConnectionError()));
|
||||
if (d->connection->state() == SshConnection::Connected) {
|
||||
@@ -84,22 +85,10 @@ void DeviceUsedPortsGatherer::start(const IDevice::ConstPtr &device)
|
||||
|
||||
void DeviceUsedPortsGatherer::handleConnectionEstablished()
|
||||
{
|
||||
QString command = d->command;
|
||||
if (command.isEmpty()) {
|
||||
QString procFilePath;
|
||||
int addressLength;
|
||||
if (d->connection->connectionInfo().localAddress.protocol() == QAbstractSocket::IPv4Protocol) {
|
||||
procFilePath = QLatin1String("/proc/net/tcp");
|
||||
addressLength = 8;
|
||||
} else {
|
||||
procFilePath = QLatin1String("/proc/net/tcp6");
|
||||
addressLength = 32;
|
||||
}
|
||||
command = QString::fromLatin1("sed "
|
||||
"'s/.*: [[:xdigit:]]\\{%1\\}:\\([[:xdigit:]]\\{4\\}\\).*/\\1/g' %2")
|
||||
.arg(addressLength).arg(procFilePath);
|
||||
}
|
||||
d->process = d->connection->createRemoteProcess(command.toUtf8());
|
||||
const QAbstractSocket::NetworkLayerProtocol protocol
|
||||
= d->connection->connectionInfo().localAddress.protocol();
|
||||
const QByteArray commandLine = d->device->portsGatheringMethod()->commandLine(protocol);
|
||||
d->process = d->connection->createRemoteProcess(commandLine);
|
||||
|
||||
connect(d->process.data(), SIGNAL(closed(int)), SLOT(handleProcessClosed(int)));
|
||||
connect(d->process.data(), SIGNAL(readyReadStandardOutput()), SLOT(handleRemoteStdOut()));
|
||||
@@ -138,27 +127,13 @@ QList<int> DeviceUsedPortsGatherer::usedPorts() const
|
||||
return d->usedPorts;
|
||||
}
|
||||
|
||||
void DeviceUsedPortsGatherer::setCommand(const QString &command)
|
||||
{
|
||||
d->command = command;
|
||||
}
|
||||
|
||||
void DeviceUsedPortsGatherer::setupUsedPorts()
|
||||
{
|
||||
QList<QByteArray> portStrings = d->remoteStdout.split('\n');
|
||||
portStrings.removeFirst();
|
||||
foreach (const QByteArray &portString, portStrings) {
|
||||
if (portString.isEmpty())
|
||||
continue;
|
||||
bool ok;
|
||||
const int port = portString.toInt(&ok, 16);
|
||||
if (ok) {
|
||||
if (d->portsToCheck.contains(port) && !d->usedPorts.contains(port))
|
||||
d->usedPorts << port;
|
||||
} else {
|
||||
qWarning("%s: Unexpected string '%s' is not a port.",
|
||||
Q_FUNC_INFO, portString.data());
|
||||
}
|
||||
d->usedPorts.clear();
|
||||
const QList<int> usedPorts = d->device->portsGatheringMethod()->usedPorts(d->remoteStdout);
|
||||
foreach (const int port, usedPorts) {
|
||||
if (d->device->freePorts().contains(port))
|
||||
d->usedPorts << port;
|
||||
}
|
||||
emit portListReady();
|
||||
}
|
||||
|
||||
@@ -50,8 +50,6 @@ public:
|
||||
int getNextFreePort(Utils::PortList *freePorts) const; // returns -1 if no more are left
|
||||
QList<int> usedPorts() const;
|
||||
|
||||
void setCommand(const QString &command); // Will use default command if not set
|
||||
|
||||
signals:
|
||||
void error(const QString &errMsg);
|
||||
void portListReady();
|
||||
|
||||
@@ -190,6 +190,9 @@ public:
|
||||
};
|
||||
} // namespace Internal
|
||||
|
||||
PortsGatheringMethod::~PortsGatheringMethod() { }
|
||||
DeviceProcessSupport::~DeviceProcessSupport() { }
|
||||
|
||||
IDevice::IDevice() : d(new Internal::IDevicePrivate)
|
||||
{ }
|
||||
|
||||
@@ -246,6 +249,16 @@ Core::Id IDevice::id() const
|
||||
return d->id;
|
||||
}
|
||||
|
||||
DeviceProcessSupport::Ptr IDevice::processSupport() const
|
||||
{
|
||||
return DeviceProcessSupport::Ptr();
|
||||
}
|
||||
|
||||
PortsGatheringMethod::Ptr IDevice::portsGatheringMethod() const
|
||||
{
|
||||
return PortsGatheringMethod::Ptr();
|
||||
}
|
||||
|
||||
IDevice::DeviceState IDevice::deviceState() const
|
||||
{
|
||||
return d->deviceState;
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
|
||||
#include <coreplugin/id.h>
|
||||
|
||||
#include <QAbstractSocket>
|
||||
#include <QList>
|
||||
#include <QSharedPointer>
|
||||
#include <QVariantMap>
|
||||
@@ -62,6 +63,29 @@ public:
|
||||
QString exe;
|
||||
};
|
||||
|
||||
class PROJECTEXPLORER_EXPORT DeviceProcessSupport
|
||||
{
|
||||
public:
|
||||
typedef QSharedPointer<const DeviceProcessSupport> Ptr;
|
||||
|
||||
virtual ~DeviceProcessSupport();
|
||||
virtual QString listProcessesCommandLine() const = 0;
|
||||
virtual QList<DeviceProcess> buildProcessList(const QString &listProcessesReply) const = 0;
|
||||
virtual QString killProcessByPidCommandLine(int pid) const = 0;
|
||||
virtual QString killProcessByNameCommandLine(const QString &filePath) const = 0;
|
||||
};
|
||||
|
||||
class PROJECTEXPLORER_EXPORT PortsGatheringMethod
|
||||
{
|
||||
public:
|
||||
typedef QSharedPointer<const PortsGatheringMethod> Ptr;
|
||||
|
||||
virtual ~PortsGatheringMethod();
|
||||
virtual QByteArray commandLine(QAbstractSocket::NetworkLayerProtocol protocol) const = 0;
|
||||
virtual QList<int> usedPorts(const QByteArray &commandOutput) const = 0;
|
||||
};
|
||||
|
||||
|
||||
// See cpp file for documentation.
|
||||
class PROJECTEXPLORER_EXPORT IDevice
|
||||
{
|
||||
@@ -99,9 +123,8 @@ public:
|
||||
virtual QString displayNameForActionId(Core::Id actionId) const = 0;
|
||||
virtual void executeAction(Core::Id actionId, QWidget *parent = 0) const = 0;
|
||||
|
||||
virtual QString listProcessesCommandLine() const = 0;
|
||||
virtual QString killProcessCommandLine(const DeviceProcess &process) const = 0;
|
||||
virtual QList<DeviceProcess> buildProcessList(const QString &listProcessesReply) const = 0;
|
||||
virtual DeviceProcessSupport::Ptr processSupport() const;
|
||||
virtual PortsGatheringMethod::Ptr portsGatheringMethod() const;
|
||||
|
||||
enum DeviceState { DeviceReadyToUse, DeviceConnected, DeviceDisconnected, DeviceStateUnknown };
|
||||
DeviceState deviceState() const;
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
include(projectexplorer_dependencies.pri)
|
||||
LIBS *= -l$$qtLibraryName(ProjectExplorer)
|
||||
QT *= network
|
||||
|
||||
@@ -328,5 +328,10 @@ QtcPlugin {
|
||||
"abstractmsvctoolchain.h"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
ProductModule {
|
||||
Depends { name: "cpp" }
|
||||
Depends { name: "Qt"; submodules: ["network"] }
|
||||
cpp.includePaths: [".."]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,6 @@
|
||||
#include <projectexplorer/projectexplorerconstants.h>
|
||||
#include <projectexplorer/target.h>
|
||||
#include <remotelinux/remotelinuxrunconfiguration.h>
|
||||
#include <remotelinux/remotelinuxutils.h>
|
||||
#include <utils/portlist.h>
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
@@ -81,7 +80,8 @@ void RemoteLinuxQmlProfilerRunner::stop()
|
||||
if (m_port == 0)
|
||||
m_portsGatherer->stop();
|
||||
else
|
||||
m_runner->stop(RemoteLinuxUtils::killApplicationCommandLine(m_remoteExecutable).toUtf8());
|
||||
m_runner->stop(m_device->processSupport()
|
||||
->killProcessByNameCommandLine(m_remoteExecutable).toUtf8());
|
||||
m_port = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -77,14 +77,6 @@ const char QNX_QNX_OS_TYPE[] = "QnxOsType";
|
||||
|
||||
const char QNX_DEBUG_TOKEN_KEY[] = "debugToken";
|
||||
|
||||
const char QNX_PORT_GATHERER_COMMAND[] = "netstat -na "
|
||||
"| sed 's/[a-z]\\+\\s\\+[0-9]\\+\\s\\+[0-9]\\+\\s\\+\\(\\*\\|[0-9\\.]\\+\\)\\.\\([0-9]\\+\\).*/\\2/g' "
|
||||
"| while read line; do "
|
||||
"if [[ $line != udp* ]] && [[ $line != Active* ]]; then "
|
||||
"printf '%x\n' $line; "
|
||||
"fi; "
|
||||
"done";
|
||||
|
||||
const char QNX_BAR_DESCRIPTOR_WIZARD_ID[] = "Q.QnxBlackBerryBarDescriptor";
|
||||
const char QNX_BLACKBERRY_QTQUICK_APP_WIZARD_ID[] = "Q.QnxBlackBerryQQApp";
|
||||
const char QNX_BLACKBERRY_QTQUICK2_APP_WIZARD_ID[] = "Q.QnxBlackBerryQQ2App";
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
#include "qnxdebugsupport.h"
|
||||
#include "qnxconstants.h"
|
||||
#include "qnxrunconfiguration.h"
|
||||
#include "qnxutils.h"
|
||||
|
||||
#include <debugger/debuggerengine.h>
|
||||
#include <projectexplorer/devicesupport/deviceapplicationrunner.h>
|
||||
@@ -62,7 +61,6 @@ QnxDebugSupport::QnxDebugSupport(QnxRunConfiguration *runConfig, Debugger::Debug
|
||||
{
|
||||
m_runner = new DeviceApplicationRunner(this);
|
||||
m_portsGatherer = new DeviceUsedPortsGatherer(this);
|
||||
m_portsGatherer->setCommand(QLatin1String(Constants::QNX_PORT_GATHERER_COMMAND));
|
||||
|
||||
connect(m_portsGatherer, SIGNAL(error(QString)), SLOT(handleError(QString)));
|
||||
connect(m_portsGatherer, SIGNAL(portListReady()), SLOT(handlePortListReady()));
|
||||
@@ -135,7 +133,7 @@ void QnxDebugSupport::handleDebuggingFinished()
|
||||
void QnxDebugSupport::setFinished()
|
||||
{
|
||||
m_state = Inactive;
|
||||
m_runner->stop(QnxUtils::applicationKillCommand(m_executable).toUtf8());
|
||||
m_runner->stop(m_device->processSupport()->killProcessByNameCommandLine(m_executable).toUtf8());
|
||||
}
|
||||
|
||||
void QnxDebugSupport::handleProgressReport(const QString &progressOutput)
|
||||
|
||||
@@ -36,6 +36,57 @@
|
||||
using namespace Qnx;
|
||||
using namespace Qnx::Internal;
|
||||
|
||||
class QnxDeviceProcessSupport : public RemoteLinux::LinuxDeviceProcessSupport
|
||||
{
|
||||
QString killProcessByNameCommandLine(const QString &filePath) const
|
||||
{
|
||||
QString executable = filePath;
|
||||
return QString::fromLatin1("for PID in $(ps -f -o pid,comm | grep %1 | awk '/%1/ {print $1}'); "
|
||||
"do "
|
||||
"kill $PID; sleep 1; kill -9 $PID; "
|
||||
"done").arg(executable.replace(QLatin1String("/"), QLatin1String("\\/")));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class QnxPortsGatheringMethod : public ProjectExplorer::PortsGatheringMethod
|
||||
{
|
||||
// TODO: The command is probably needlessly complicated because the parsing method
|
||||
// used to be fixed. These two can now be matched to each other.
|
||||
QByteArray commandLine(QAbstractSocket::NetworkLayerProtocol protocol) const
|
||||
{
|
||||
Q_UNUSED(protocol);
|
||||
return "netstat -na "
|
||||
"| sed 's/[a-z]\\+\\s\\+[0-9]\\+\\s\\+[0-9]\\+\\s\\+\\(\\*\\|[0-9\\.]\\+\\)\\.\\([0-9]\\+\\).*/\\2/g' "
|
||||
"| while read line; do "
|
||||
"if [[ $line != udp* ]] && [[ $line != Active* ]]; then "
|
||||
"printf '%x\n' $line; "
|
||||
"fi; "
|
||||
"done";
|
||||
}
|
||||
|
||||
QList<int> usedPorts(const QByteArray &output) const
|
||||
{
|
||||
QList<int> ports;
|
||||
QList<QByteArray> portStrings = output.split('\n');
|
||||
portStrings.removeFirst();
|
||||
foreach (const QByteArray &portString, portStrings) {
|
||||
if (portString.isEmpty())
|
||||
continue;
|
||||
bool ok;
|
||||
const int port = portString.toInt(&ok, 16);
|
||||
if (ok) {
|
||||
if (!ports.contains(port))
|
||||
ports << port;
|
||||
} else {
|
||||
qWarning("%s: Unexpected string '%s' is not a port.",
|
||||
Q_FUNC_INFO, portString.data());
|
||||
}
|
||||
}
|
||||
return ports;
|
||||
}
|
||||
};
|
||||
|
||||
QnxDeviceConfiguration::QnxDeviceConfiguration()
|
||||
: RemoteLinux::LinuxDevice()
|
||||
{
|
||||
@@ -72,3 +123,12 @@ ProjectExplorer::IDevice::Ptr QnxDeviceConfiguration::clone() const
|
||||
return Ptr(new QnxDeviceConfiguration(*this));
|
||||
}
|
||||
|
||||
ProjectExplorer::DeviceProcessSupport::Ptr QnxDeviceConfiguration::processSupport() const
|
||||
{
|
||||
return ProjectExplorer::DeviceProcessSupport::Ptr(new QnxDeviceProcessSupport);
|
||||
}
|
||||
|
||||
ProjectExplorer::PortsGatheringMethod::Ptr QnxDeviceConfiguration::portsGatheringMethod() const
|
||||
{
|
||||
return ProjectExplorer::PortsGatheringMethod::Ptr(new QnxPortsGatheringMethod);
|
||||
}
|
||||
|
||||
@@ -52,6 +52,9 @@ public:
|
||||
Origin origin = ManuallyAdded, Core::Id id = Core::Id());
|
||||
ProjectExplorer::IDevice::Ptr clone() const;
|
||||
|
||||
ProjectExplorer::DeviceProcessSupport::Ptr processSupport() const;
|
||||
ProjectExplorer::PortsGatheringMethod::Ptr portsGatheringMethod() const;
|
||||
|
||||
QString displayType() const;
|
||||
|
||||
protected:
|
||||
|
||||
@@ -81,8 +81,6 @@ IDevice::Ptr QnxDeviceConfigurationWizard::device()
|
||||
device->setFreePorts(Utils::PortList::fromString(QLatin1String("10000-10100")));
|
||||
|
||||
RemoteLinux::GenericLinuxDeviceTester *devTester = new RemoteLinux::GenericLinuxDeviceTester(this);
|
||||
devTester->usedPortsGatherer()->setCommand(QLatin1String(Constants::QNX_PORT_GATHERER_COMMAND));
|
||||
|
||||
RemoteLinux::LinuxDeviceTestDialog dlg(device, devTester, this);
|
||||
dlg.exec();
|
||||
|
||||
|
||||
@@ -33,7 +33,6 @@
|
||||
|
||||
#include "qnxruncontrol.h"
|
||||
#include "qnxrunconfiguration.h"
|
||||
#include "qnxutils.h"
|
||||
|
||||
#include <projectexplorer/runconfiguration.h>
|
||||
#include <remotelinux/remotelinuxrunconfiguration.h>
|
||||
@@ -45,9 +44,4 @@ using namespace RemoteLinux;
|
||||
QnxRunControl::QnxRunControl(ProjectExplorer::RunConfiguration *runConfig)
|
||||
: RemoteLinuxRunControl(runConfig)
|
||||
{
|
||||
const RemoteLinuxRunConfiguration * const rc
|
||||
= qobject_cast<RemoteLinuxRunConfiguration *>(runConfig);
|
||||
QString executable = rc->remoteExecutableFilePath();
|
||||
executable.replace(QLatin1String("/"), QLatin1String("\\/"));
|
||||
overrideStopCommandLine(QnxUtils::applicationKillCommand(executable).toUtf8());
|
||||
}
|
||||
|
||||
@@ -75,11 +75,3 @@ QStringList QnxUtils::searchPaths(QnxAbstractQtVersion *qtVersion)
|
||||
|
||||
return searchPaths;
|
||||
}
|
||||
|
||||
QString QnxUtils::applicationKillCommand(const QString &applicationFilePath)
|
||||
{
|
||||
return QString::fromLatin1("for PID in $(ps -f -o pid,comm | grep %1 | awk '/%1/ {print $1}'); "
|
||||
"do "
|
||||
"kill $PID; sleep 1; kill -9 $PID; "
|
||||
"done").arg(applicationFilePath);
|
||||
}
|
||||
|
||||
@@ -49,7 +49,6 @@ public:
|
||||
static QString addQuotes(const QString &string);
|
||||
static Qnx::QnxArchitecture cpudirToArch(const QString &cpuDir);
|
||||
static QStringList searchPaths(QnxAbstractQtVersion *qtVersion);
|
||||
static QString applicationKillCommand(const QString &applicationFilePath);
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
@@ -249,21 +249,4 @@ void SymbianIDevice::updateState()
|
||||
}
|
||||
}
|
||||
|
||||
QString SymbianIDevice::listProcessesCommandLine() const
|
||||
{
|
||||
return QString();
|
||||
}
|
||||
|
||||
QString SymbianIDevice::killProcessCommandLine(const DeviceProcess &process) const
|
||||
{
|
||||
Q_UNUSED(process);
|
||||
return QString();
|
||||
}
|
||||
|
||||
QList<DeviceProcess> SymbianIDevice::buildProcessList(const QString &listProcessesReply) const
|
||||
{
|
||||
Q_UNUSED(listProcessesReply);
|
||||
return QList<DeviceProcess>();
|
||||
}
|
||||
|
||||
} // namespace qt4projectmanager
|
||||
|
||||
@@ -78,10 +78,6 @@ public:
|
||||
QString displayNameForActionId(Core::Id actionId) const;
|
||||
void executeAction(Core::Id actionId, QWidget*parent) const;
|
||||
|
||||
QString listProcessesCommandLine() const;
|
||||
QString killProcessCommandLine(const ProjectExplorer::DeviceProcess &process) const;
|
||||
QList<ProjectExplorer::DeviceProcess> buildProcessList(const QString &listProcessesReply) const;
|
||||
|
||||
protected:
|
||||
SymbianIDevice(const SymbianIDevice &other);
|
||||
SymbianIDevice &operator=(const SymbianIDevice &); // no impl.
|
||||
|
||||
@@ -54,6 +54,119 @@ static QString visualizeNull(QString s)
|
||||
return s.replace(QLatin1Char('\0'), QLatin1String("<null>"));
|
||||
}
|
||||
|
||||
QString LinuxDeviceProcessSupport::listProcessesCommandLine() const
|
||||
{
|
||||
return QString::fromLatin1(
|
||||
"for dir in `ls -d /proc/[0123456789]*`; do "
|
||||
"test -d $dir || continue;" // Decrease the likelihood of a race condition.
|
||||
"echo $dir;"
|
||||
"cat $dir/cmdline;echo;" // cmdline does not end in newline
|
||||
"cat $dir/stat;"
|
||||
"readlink $dir/exe;"
|
||||
"printf '%1''%2';"
|
||||
"done").arg(Delimiter0).arg(Delimiter1);
|
||||
}
|
||||
|
||||
QList<DeviceProcess> LinuxDeviceProcessSupport::buildProcessList(const QString &listProcessesReply) const
|
||||
{
|
||||
QList<DeviceProcess> processes;
|
||||
const QStringList lines = listProcessesReply.split(QString::fromLatin1(Delimiter0)
|
||||
+ QString::fromLatin1(Delimiter1), QString::SkipEmptyParts);
|
||||
foreach (const QString &line, lines) {
|
||||
const QStringList elements = line.split(QLatin1Char('\n'));
|
||||
if (elements.count() < 4) {
|
||||
qDebug("%s: Expected four list elements, got %d. Line was '%s'.", Q_FUNC_INFO,
|
||||
elements.count(), qPrintable(visualizeNull(line)));
|
||||
continue;
|
||||
}
|
||||
bool ok;
|
||||
const int pid = elements.first().mid(6).toInt(&ok);
|
||||
if (!ok) {
|
||||
qDebug("%s: Expected number in %s. Line was '%s'.", Q_FUNC_INFO,
|
||||
qPrintable(elements.first()), qPrintable(visualizeNull(line)));
|
||||
continue;
|
||||
}
|
||||
QString command = elements.at(1);
|
||||
command.replace(QLatin1Char('\0'), QLatin1Char(' '));
|
||||
if (command.isEmpty()) {
|
||||
const QString &statString = elements.at(2);
|
||||
const int openParenPos = statString.indexOf(QLatin1Char('('));
|
||||
const int closedParenPos = statString.indexOf(QLatin1Char(')'), openParenPos);
|
||||
if (openParenPos == -1 || closedParenPos == -1)
|
||||
continue;
|
||||
command = QLatin1Char('[')
|
||||
+ statString.mid(openParenPos + 1, closedParenPos - openParenPos - 1)
|
||||
+ QLatin1Char(']');
|
||||
}
|
||||
|
||||
DeviceProcess process;
|
||||
process.pid = pid;
|
||||
process.cmdLine = command;
|
||||
process.exe = elements.at(3);
|
||||
processes.append(process);
|
||||
}
|
||||
|
||||
qSort(processes);
|
||||
return processes;
|
||||
}
|
||||
|
||||
QString LinuxDeviceProcessSupport::killProcessByPidCommandLine(int pid) const
|
||||
{
|
||||
return QLatin1String("kill -9 ") + QString::number(pid);
|
||||
}
|
||||
|
||||
QString LinuxDeviceProcessSupport::killProcessByNameCommandLine(const QString &filePath) const
|
||||
{
|
||||
return QString::fromLatin1("cd /proc; for pid in `ls -d [0123456789]*`; "
|
||||
"do "
|
||||
"if [ \"`readlink /proc/$pid/exe`\" = \"%1\" ]; then "
|
||||
" kill $pid; sleep 1; kill -9 $pid; "
|
||||
"fi; "
|
||||
"done").arg(filePath);
|
||||
}
|
||||
|
||||
|
||||
class LinuxPortsGatheringMethod : public ProjectExplorer::PortsGatheringMethod
|
||||
{
|
||||
QByteArray commandLine(QAbstractSocket::NetworkLayerProtocol protocol) const
|
||||
{
|
||||
QString procFilePath;
|
||||
int addressLength;
|
||||
if (protocol == QAbstractSocket::IPv4Protocol) {
|
||||
procFilePath = QLatin1String("/proc/net/tcp");
|
||||
addressLength = 8;
|
||||
} else {
|
||||
procFilePath = QLatin1String("/proc/net/tcp6");
|
||||
addressLength = 32;
|
||||
}
|
||||
return QString::fromLatin1("sed "
|
||||
"'s/.*: [[:xdigit:]]\\{%1\\}:\\([[:xdigit:]]\\{4\\}\\).*/\\1/g' %2")
|
||||
.arg(addressLength).arg(procFilePath).toUtf8();
|
||||
}
|
||||
|
||||
QList<int> usedPorts(const QByteArray &output) const
|
||||
{
|
||||
QList<int> ports;
|
||||
QList<QByteArray> portStrings = output.split('\n');
|
||||
portStrings.removeFirst();
|
||||
foreach (const QByteArray &portString, portStrings) {
|
||||
if (portString.isEmpty())
|
||||
continue;
|
||||
bool ok;
|
||||
const int port = portString.toInt(&ok, 16);
|
||||
if (ok) {
|
||||
if (!ports.contains(port))
|
||||
ports << port;
|
||||
} else {
|
||||
qWarning("%s: Unexpected string '%s' is not a port.",
|
||||
Q_FUNC_INFO, portString.data());
|
||||
}
|
||||
}
|
||||
return ports;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
LinuxDevice::Ptr LinuxDevice::create(const QString &name,
|
||||
Core::Id type, MachineType machineType, Origin origin, Core::Id id)
|
||||
{
|
||||
@@ -128,65 +241,14 @@ ProjectExplorer::IDevice::Ptr LinuxDevice::clone() const
|
||||
return Ptr(new LinuxDevice(*this));
|
||||
}
|
||||
|
||||
QString LinuxDevice::listProcessesCommandLine() const
|
||||
DeviceProcessSupport::Ptr LinuxDevice::processSupport() const
|
||||
{
|
||||
return QString::fromLatin1(
|
||||
"for dir in `ls -d /proc/[0123456789]*`; do "
|
||||
"test -d $dir || continue;" // Decrease the likelihood of a race condition.
|
||||
"echo $dir;"
|
||||
"cat $dir/cmdline;echo;" // cmdline does not end in newline
|
||||
"cat $dir/stat;"
|
||||
"readlink $dir/exe;"
|
||||
"printf '%1''%2';"
|
||||
"done").arg(Delimiter0).arg(Delimiter1);
|
||||
return DeviceProcessSupport::Ptr(new LinuxDeviceProcessSupport);
|
||||
}
|
||||
|
||||
QString LinuxDevice::killProcessCommandLine(const DeviceProcess &process) const
|
||||
PortsGatheringMethod::Ptr LinuxDevice::portsGatheringMethod() const
|
||||
{
|
||||
return QLatin1String("kill -9 ") + QString::number(process.pid);
|
||||
}
|
||||
|
||||
QList<DeviceProcess> LinuxDevice::buildProcessList(const QString &listProcessesReply) const
|
||||
{
|
||||
QList<DeviceProcess> processes;
|
||||
const QStringList lines = listProcessesReply.split(QString::fromLatin1(Delimiter0)
|
||||
+ QString::fromLatin1(Delimiter1), QString::SkipEmptyParts);
|
||||
foreach (const QString &line, lines) {
|
||||
const QStringList elements = line.split(QLatin1Char('\n'));
|
||||
if (elements.count() < 4) {
|
||||
qDebug("%s: Expected four list elements, got %d. Line was '%s'.", Q_FUNC_INFO,
|
||||
elements.count(), qPrintable(visualizeNull(line)));
|
||||
continue;
|
||||
}
|
||||
bool ok;
|
||||
const int pid = elements.first().mid(6).toInt(&ok);
|
||||
if (!ok) {
|
||||
qDebug("%s: Expected number in %s. Line was '%s'.", Q_FUNC_INFO,
|
||||
qPrintable(elements.first()), qPrintable(visualizeNull(line)));
|
||||
continue;
|
||||
}
|
||||
QString command = elements.at(1);
|
||||
command.replace(QLatin1Char('\0'), QLatin1Char(' '));
|
||||
if (command.isEmpty()) {
|
||||
const QString &statString = elements.at(2);
|
||||
const int openParenPos = statString.indexOf(QLatin1Char('('));
|
||||
const int closedParenPos = statString.indexOf(QLatin1Char(')'), openParenPos);
|
||||
if (openParenPos == -1 || closedParenPos == -1)
|
||||
continue;
|
||||
command = QLatin1Char('[')
|
||||
+ statString.mid(openParenPos + 1, closedParenPos - openParenPos - 1)
|
||||
+ QLatin1Char(']');
|
||||
}
|
||||
|
||||
DeviceProcess process;
|
||||
process.pid = pid;
|
||||
process.cmdLine = command;
|
||||
process.exe = elements.at(3);
|
||||
processes.append(process);
|
||||
}
|
||||
|
||||
qSort(processes);
|
||||
return processes;
|
||||
return LinuxPortsGatheringMethod::Ptr(new LinuxPortsGatheringMethod);
|
||||
}
|
||||
|
||||
} // namespace RemoteLinux
|
||||
|
||||
@@ -43,6 +43,15 @@ namespace Utils { class PortList; }
|
||||
namespace RemoteLinux {
|
||||
namespace Internal { class LinuxDevicePrivate; }
|
||||
|
||||
class REMOTELINUX_EXPORT LinuxDeviceProcessSupport : public ProjectExplorer::DeviceProcessSupport
|
||||
{
|
||||
public:
|
||||
QString listProcessesCommandLine() const;
|
||||
QList<ProjectExplorer::DeviceProcess> buildProcessList(const QString &listProcessesReply) const;
|
||||
QString killProcessByPidCommandLine(int pid) const;
|
||||
QString killProcessByNameCommandLine(const QString &filePath) const;
|
||||
};
|
||||
|
||||
class REMOTELINUX_EXPORT LinuxDevice : public ProjectExplorer::IDevice
|
||||
{
|
||||
Q_DECLARE_TR_FUNCTIONS(RemoteLinux::Internal::LinuxDevice)
|
||||
@@ -62,9 +71,8 @@ public:
|
||||
void executeAction(Core::Id actionId, QWidget *parent) const;
|
||||
ProjectExplorer::IDevice::Ptr clone() const;
|
||||
|
||||
QString listProcessesCommandLine() const;
|
||||
QString killProcessCommandLine(const ProjectExplorer::DeviceProcess &process) const;
|
||||
QList<ProjectExplorer::DeviceProcess> buildProcessList(const QString &listProcessesReply) const;
|
||||
ProjectExplorer::DeviceProcessSupport::Ptr processSupport() const;
|
||||
ProjectExplorer::PortsGatheringMethod::Ptr portsGatheringMethod() const;
|
||||
|
||||
protected:
|
||||
LinuxDevice() {}
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
#include "remotelinuxdebugsupport.h"
|
||||
|
||||
#include "remotelinuxrunconfiguration.h"
|
||||
#include "remotelinuxutils.h"
|
||||
|
||||
#include <debugger/debuggerengine.h>
|
||||
#include <debugger/debuggerstartparameters.h>
|
||||
@@ -306,8 +305,11 @@ void LinuxDeviceDebugSupport::setFinished()
|
||||
return;
|
||||
d->portsGatherer.disconnect(this);
|
||||
d->appRunner.disconnect(this);
|
||||
if (d->state == StartingRunner)
|
||||
d->appRunner.stop(RemoteLinuxUtils::killApplicationCommandLine(d->remoteFilePath).toUtf8());
|
||||
if (d->state == StartingRunner) {
|
||||
const QString stopCommand
|
||||
= d->device->processSupport()->killProcessByNameCommandLine(d->remoteFilePath);
|
||||
d->appRunner.stop(stopCommand.toUtf8());
|
||||
}
|
||||
d->state = Inactive;
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
#include "remotelinux_constants.h"
|
||||
#include "remotelinuxdeployconfigurationfactory.h"
|
||||
#include "remotelinuxrunconfiguration.h"
|
||||
#include "remotelinuxutils.h"
|
||||
|
||||
#include <projectexplorer/profileinformation.h>
|
||||
#include <projectexplorer/target.h>
|
||||
|
||||
@@ -31,7 +31,6 @@
|
||||
|
||||
#include "remotelinuxrunconfiguration.h"
|
||||
#include "remotelinuxenvironmentreader.h"
|
||||
#include "remotelinuxutils.h"
|
||||
|
||||
#include <coreplugin/coreconstants.h>
|
||||
#include <coreplugin/icore.h>
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
#include "remotelinuxruncontrol.h"
|
||||
|
||||
#include "remotelinuxrunconfiguration.h"
|
||||
#include "remotelinuxutils.h"
|
||||
|
||||
#include <projectexplorer/devicesupport/deviceapplicationrunner.h>
|
||||
#include <projectexplorer/profileinformation.h>
|
||||
@@ -54,7 +53,6 @@ public:
|
||||
QString remoteExecutable;
|
||||
QString arguments;
|
||||
QString prefix;
|
||||
QByteArray stopCommand;
|
||||
};
|
||||
|
||||
RemoteLinuxRunControl::RemoteLinuxRunControl(RunConfiguration *rc)
|
||||
@@ -66,7 +64,6 @@ RemoteLinuxRunControl::RemoteLinuxRunControl(RunConfiguration *rc)
|
||||
d->remoteExecutable = lrc->remoteExecutableFilePath();
|
||||
d->arguments = lrc->arguments();
|
||||
d->prefix = lrc->commandPrefix();
|
||||
d->stopCommand = RemoteLinuxUtils::killApplicationCommandLine(d->remoteExecutable).toUtf8();
|
||||
}
|
||||
|
||||
RemoteLinuxRunControl::~RemoteLinuxRunControl()
|
||||
@@ -92,7 +89,9 @@ void RemoteLinuxRunControl::start()
|
||||
|
||||
RunControl::StopResult RemoteLinuxRunControl::stop()
|
||||
{
|
||||
d->runner.stop(d->stopCommand);
|
||||
const QString stopCommandLine
|
||||
= d->device->processSupport()->killProcessByNameCommandLine(d->remoteExecutable);
|
||||
d->runner.stop(stopCommandLine.toUtf8());
|
||||
return AsynchronousStop;
|
||||
}
|
||||
|
||||
@@ -141,11 +140,6 @@ void RemoteLinuxRunControl::setApplicationRunnerPostRunAction(DeviceApplicationH
|
||||
d->runner.setPostRunAction(action);
|
||||
}
|
||||
|
||||
void RemoteLinuxRunControl::overrideStopCommandLine(const QByteArray &commandLine)
|
||||
{
|
||||
d->stopCommand = commandLine;
|
||||
}
|
||||
|
||||
void RemoteLinuxRunControl::setFinished()
|
||||
{
|
||||
d->runner.disconnect(this);
|
||||
|
||||
@@ -52,7 +52,6 @@ public:
|
||||
|
||||
void setApplicationRunnerPreRunAction(ProjectExplorer::DeviceApplicationHelperAction *action);
|
||||
void setApplicationRunnerPostRunAction(ProjectExplorer::DeviceApplicationHelperAction *action);
|
||||
void overrideStopCommandLine(const QByteArray &commandLine);
|
||||
|
||||
private slots:
|
||||
void handleErrorMessage(const QString &error);
|
||||
|
||||
@@ -29,20 +29,6 @@
|
||||
**************************************************************************/
|
||||
#include "remotelinuxutils.h"
|
||||
|
||||
#include "linuxdevice.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
|
||||
namespace RemoteLinux {
|
||||
|
||||
QString RemoteLinuxUtils::killApplicationCommandLine(const QString &applicationFilePath)
|
||||
{
|
||||
return QString::fromLatin1("cd /proc; for pid in `ls -d [0123456789]*`; "
|
||||
"do "
|
||||
"if [ \"`readlink /proc/$pid/exe`\" = \"%1\" ]; then "
|
||||
" kill $pid; sleep 1; kill -9 $pid; "
|
||||
"fi; "
|
||||
"done").arg(applicationFilePath);
|
||||
}
|
||||
|
||||
} // namespace RemoteLinux
|
||||
|
||||
@@ -32,15 +32,11 @@
|
||||
|
||||
#include "remotelinux_export.h"
|
||||
|
||||
#include <QSharedPointer>
|
||||
|
||||
namespace RemoteLinux {
|
||||
class LinuxDevice;
|
||||
|
||||
class REMOTELINUX_EXPORT RemoteLinuxUtils
|
||||
{
|
||||
public:
|
||||
static QString killApplicationCommandLine(const QString &applicationFilePath);
|
||||
};
|
||||
|
||||
} // namespace RemoteLinux
|
||||
|
||||
Reference in New Issue
Block a user