diff --git a/src/plugins/android/androiddevice.cpp b/src/plugins/android/androiddevice.cpp index 83ee64d9401..42e698e0442 100644 --- a/src/plugins/android/androiddevice.cpp +++ b/src/plugins/android/androiddevice.cpp @@ -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 AndroidDevice::buildProcessList(const QString &listProcessesReply) const -{ - Q_UNUSED(listProcessesReply); - return QList(); -} - } // namespace Internal } // namespace Android diff --git a/src/plugins/android/androiddevice.h b/src/plugins/android/androiddevice.h index f38f82cc139..e4b8e28ce38 100644 --- a/src/plugins/android/androiddevice.h +++ b/src/plugins/android/androiddevice.h @@ -51,10 +51,6 @@ public: ProjectExplorer::IDevice::Ptr clone() const; - QString listProcessesCommandLine() const; - QString killProcessCommandLine(const ProjectExplorer::DeviceProcess &process) const; - QList buildProcessList(const QString &listProcessesReply) const; - protected: friend class AndroidDeviceFactory; friend class Android::AndroidPlugin; diff --git a/src/plugins/projectexplorer/devicesupport/desktopdevice.cpp b/src/plugins/projectexplorer/devicesupport/desktopdevice.cpp index 31b11975fd7..15c6fee7ea1 100644 --- a/src/plugins/projectexplorer/devicesupport/desktopdevice.cpp +++ b/src/plugins/projectexplorer/devicesupport/desktopdevice.cpp @@ -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 DesktopDevice::buildProcessList(const QString &listProcessesReply) const -{ - Q_UNUSED(listProcessesReply); - return QList(); -} - } // namespace ProjectExplorer diff --git a/src/plugins/projectexplorer/devicesupport/desktopdevice.h b/src/plugins/projectexplorer/devicesupport/desktopdevice.h index bd852ab45ce..4fb3857ca8c 100644 --- a/src/plugins/projectexplorer/devicesupport/desktopdevice.h +++ b/src/plugins/projectexplorer/devicesupport/desktopdevice.h @@ -54,10 +54,6 @@ public: IDevice::Ptr clone() const; - QString listProcessesCommandLine() const; - QString killProcessCommandLine(const DeviceProcess &process) const; - QList buildProcessList(const QString &listProcessesReply) const; - protected: DesktopDevice(); DesktopDevice(const DesktopDevice &other); diff --git a/src/plugins/projectexplorer/devicesupport/deviceprocesslist.cpp b/src/plugins/projectexplorer/devicesupport/deviceprocesslist.cpp index 7553c5c29f8..be2be74cfdb 100644 --- a/src/plugins/projectexplorer/devicesupport/deviceprocesslist.cpp +++ b/src/plugins/projectexplorer/devicesupport/deviceprocesslist.cpp @@ -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 processes = d->device->buildProcessList(QString::fromUtf8(remoteStdout.data(), - remoteStdout.count())); + const QString stdoutString + = QString::fromUtf8(remoteStdout.data(), remoteStdout.count()); + QList processes + = d->device->processSupport()->buildProcessList(stdoutString); if (!processes.isEmpty()) { beginInsertRows(QModelIndex(), 0, processes.count()-1); d->remoteProcesses = processes; diff --git a/src/plugins/projectexplorer/devicesupport/deviceusedportsgatherer.cpp b/src/plugins/projectexplorer/devicesupport/deviceusedportsgatherer.cpp index 8d57f9e22cf..a97e1d95fc7 100644 --- a/src/plugins/projectexplorer/devicesupport/deviceusedportsgatherer.cpp +++ b/src/plugins/projectexplorer/devicesupport/deviceusedportsgatherer.cpp @@ -46,11 +46,10 @@ class DeviceUsedPortsGathererPrivate public: SshConnection *connection; SshRemoteProcess::Ptr process; - PortList portsToCheck; QList 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 DeviceUsedPortsGatherer::usedPorts() const return d->usedPorts; } -void DeviceUsedPortsGatherer::setCommand(const QString &command) -{ - d->command = command; -} - void DeviceUsedPortsGatherer::setupUsedPorts() { - QList 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 usedPorts = d->device->portsGatheringMethod()->usedPorts(d->remoteStdout); + foreach (const int port, usedPorts) { + if (d->device->freePorts().contains(port)) + d->usedPorts << port; } emit portListReady(); } diff --git a/src/plugins/projectexplorer/devicesupport/deviceusedportsgatherer.h b/src/plugins/projectexplorer/devicesupport/deviceusedportsgatherer.h index f68dd6fa4d6..0ab94597cdd 100644 --- a/src/plugins/projectexplorer/devicesupport/deviceusedportsgatherer.h +++ b/src/plugins/projectexplorer/devicesupport/deviceusedportsgatherer.h @@ -50,8 +50,6 @@ public: int getNextFreePort(Utils::PortList *freePorts) const; // returns -1 if no more are left QList usedPorts() const; - void setCommand(const QString &command); // Will use default command if not set - signals: void error(const QString &errMsg); void portListReady(); diff --git a/src/plugins/projectexplorer/devicesupport/idevice.cpp b/src/plugins/projectexplorer/devicesupport/idevice.cpp index 13675b3dd08..5a9430b1d3f 100644 --- a/src/plugins/projectexplorer/devicesupport/idevice.cpp +++ b/src/plugins/projectexplorer/devicesupport/idevice.cpp @@ -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; diff --git a/src/plugins/projectexplorer/devicesupport/idevice.h b/src/plugins/projectexplorer/devicesupport/idevice.h index f69480fb70a..c20ae330b22 100644 --- a/src/plugins/projectexplorer/devicesupport/idevice.h +++ b/src/plugins/projectexplorer/devicesupport/idevice.h @@ -34,6 +34,7 @@ #include +#include #include #include #include @@ -62,6 +63,29 @@ public: QString exe; }; +class PROJECTEXPLORER_EXPORT DeviceProcessSupport +{ +public: + typedef QSharedPointer Ptr; + + virtual ~DeviceProcessSupport(); + virtual QString listProcessesCommandLine() const = 0; + virtual QList 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 Ptr; + + virtual ~PortsGatheringMethod(); + virtual QByteArray commandLine(QAbstractSocket::NetworkLayerProtocol protocol) const = 0; + virtual QList 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 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; diff --git a/src/plugins/projectexplorer/projectexplorer.pri b/src/plugins/projectexplorer/projectexplorer.pri index 8b464277e4e..b1df3996e2d 100644 --- a/src/plugins/projectexplorer/projectexplorer.pri +++ b/src/plugins/projectexplorer/projectexplorer.pri @@ -1,2 +1,3 @@ include(projectexplorer_dependencies.pri) LIBS *= -l$$qtLibraryName(ProjectExplorer) +QT *= network diff --git a/src/plugins/projectexplorer/projectexplorer.qbs b/src/plugins/projectexplorer/projectexplorer.qbs index 10234f3ab56..d36076c1b50 100644 --- a/src/plugins/projectexplorer/projectexplorer.qbs +++ b/src/plugins/projectexplorer/projectexplorer.qbs @@ -328,5 +328,10 @@ QtcPlugin { "abstractmsvctoolchain.h" ] } -} + ProductModule { + Depends { name: "cpp" } + Depends { name: "Qt"; submodules: ["network"] } + cpp.includePaths: [".."] + } +} diff --git a/src/plugins/qmlprofiler/remotelinuxqmlprofilerrunner.cpp b/src/plugins/qmlprofiler/remotelinuxqmlprofilerrunner.cpp index 115f406c75f..9071604230c 100644 --- a/src/plugins/qmlprofiler/remotelinuxqmlprofilerrunner.cpp +++ b/src/plugins/qmlprofiler/remotelinuxqmlprofilerrunner.cpp @@ -35,7 +35,6 @@ #include #include #include -#include #include #include @@ -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; } diff --git a/src/plugins/qnx/qnxconstants.h b/src/plugins/qnx/qnxconstants.h index 26c68cd8352..ab5a2f4b4d9 100644 --- a/src/plugins/qnx/qnxconstants.h +++ b/src/plugins/qnx/qnxconstants.h @@ -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"; diff --git a/src/plugins/qnx/qnxdebugsupport.cpp b/src/plugins/qnx/qnxdebugsupport.cpp index 766a06c9bf0..03a84db5d92 100644 --- a/src/plugins/qnx/qnxdebugsupport.cpp +++ b/src/plugins/qnx/qnxdebugsupport.cpp @@ -34,7 +34,6 @@ #include "qnxdebugsupport.h" #include "qnxconstants.h" #include "qnxrunconfiguration.h" -#include "qnxutils.h" #include #include @@ -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) diff --git a/src/plugins/qnx/qnxdeviceconfiguration.cpp b/src/plugins/qnx/qnxdeviceconfiguration.cpp index 1eb6c136d67..2c22a072372 100644 --- a/src/plugins/qnx/qnxdeviceconfiguration.cpp +++ b/src/plugins/qnx/qnxdeviceconfiguration.cpp @@ -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 usedPorts(const QByteArray &output) const + { + QList ports; + QList 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); +} diff --git a/src/plugins/qnx/qnxdeviceconfiguration.h b/src/plugins/qnx/qnxdeviceconfiguration.h index 0a68f9a9c9e..fe5bc58b8b9 100644 --- a/src/plugins/qnx/qnxdeviceconfiguration.h +++ b/src/plugins/qnx/qnxdeviceconfiguration.h @@ -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: diff --git a/src/plugins/qnx/qnxdeviceconfigurationwizard.cpp b/src/plugins/qnx/qnxdeviceconfigurationwizard.cpp index 5fba97eba0b..a113cb5e07e 100644 --- a/src/plugins/qnx/qnxdeviceconfigurationwizard.cpp +++ b/src/plugins/qnx/qnxdeviceconfigurationwizard.cpp @@ -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(); diff --git a/src/plugins/qnx/qnxruncontrol.cpp b/src/plugins/qnx/qnxruncontrol.cpp index f3cb262c56e..81940942ba7 100644 --- a/src/plugins/qnx/qnxruncontrol.cpp +++ b/src/plugins/qnx/qnxruncontrol.cpp @@ -33,7 +33,6 @@ #include "qnxruncontrol.h" #include "qnxrunconfiguration.h" -#include "qnxutils.h" #include #include @@ -45,9 +44,4 @@ using namespace RemoteLinux; QnxRunControl::QnxRunControl(ProjectExplorer::RunConfiguration *runConfig) : RemoteLinuxRunControl(runConfig) { - const RemoteLinuxRunConfiguration * const rc - = qobject_cast(runConfig); - QString executable = rc->remoteExecutableFilePath(); - executable.replace(QLatin1String("/"), QLatin1String("\\/")); - overrideStopCommandLine(QnxUtils::applicationKillCommand(executable).toUtf8()); } diff --git a/src/plugins/qnx/qnxutils.cpp b/src/plugins/qnx/qnxutils.cpp index d96b50649a0..4ef95137c97 100644 --- a/src/plugins/qnx/qnxutils.cpp +++ b/src/plugins/qnx/qnxutils.cpp @@ -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); -} diff --git a/src/plugins/qnx/qnxutils.h b/src/plugins/qnx/qnxutils.h index 82d63de8413..1195f87c579 100644 --- a/src/plugins/qnx/qnxutils.h +++ b/src/plugins/qnx/qnxutils.h @@ -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 diff --git a/src/plugins/qt4projectmanager/qt-s60/symbianidevice.cpp b/src/plugins/qt4projectmanager/qt-s60/symbianidevice.cpp index d0f0c662e1d..b084ecdac61 100644 --- a/src/plugins/qt4projectmanager/qt-s60/symbianidevice.cpp +++ b/src/plugins/qt4projectmanager/qt-s60/symbianidevice.cpp @@ -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 SymbianIDevice::buildProcessList(const QString &listProcessesReply) const -{ - Q_UNUSED(listProcessesReply); - return QList(); -} - } // namespace qt4projectmanager diff --git a/src/plugins/qt4projectmanager/qt-s60/symbianidevice.h b/src/plugins/qt4projectmanager/qt-s60/symbianidevice.h index aaba2fe407f..2a8ba273cf9 100644 --- a/src/plugins/qt4projectmanager/qt-s60/symbianidevice.h +++ b/src/plugins/qt4projectmanager/qt-s60/symbianidevice.h @@ -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 buildProcessList(const QString &listProcessesReply) const; - protected: SymbianIDevice(const SymbianIDevice &other); SymbianIDevice &operator=(const SymbianIDevice &); // no impl. diff --git a/src/plugins/remotelinux/linuxdevice.cpp b/src/plugins/remotelinux/linuxdevice.cpp index 4a3b1d968f7..864e76d0338 100644 --- a/src/plugins/remotelinux/linuxdevice.cpp +++ b/src/plugins/remotelinux/linuxdevice.cpp @@ -54,6 +54,119 @@ static QString visualizeNull(QString s) return s.replace(QLatin1Char('\0'), QLatin1String("")); } +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 LinuxDeviceProcessSupport::buildProcessList(const QString &listProcessesReply) const +{ + QList 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 usedPorts(const QByteArray &output) const + { + QList ports; + QList 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 LinuxDevice::buildProcessList(const QString &listProcessesReply) const -{ - QList 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 diff --git a/src/plugins/remotelinux/linuxdevice.h b/src/plugins/remotelinux/linuxdevice.h index 3d4a5f73294..60a05c85b81 100644 --- a/src/plugins/remotelinux/linuxdevice.h +++ b/src/plugins/remotelinux/linuxdevice.h @@ -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 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 buildProcessList(const QString &listProcessesReply) const; + ProjectExplorer::DeviceProcessSupport::Ptr processSupport() const; + ProjectExplorer::PortsGatheringMethod::Ptr portsGatheringMethod() const; protected: LinuxDevice() {} diff --git a/src/plugins/remotelinux/remotelinuxdebugsupport.cpp b/src/plugins/remotelinux/remotelinuxdebugsupport.cpp index a0f57b283df..baa5be50af1 100644 --- a/src/plugins/remotelinux/remotelinuxdebugsupport.cpp +++ b/src/plugins/remotelinux/remotelinuxdebugsupport.cpp @@ -30,7 +30,6 @@ #include "remotelinuxdebugsupport.h" #include "remotelinuxrunconfiguration.h" -#include "remotelinuxutils.h" #include #include @@ -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; } diff --git a/src/plugins/remotelinux/remotelinuxrunconfigurationfactory.cpp b/src/plugins/remotelinux/remotelinuxrunconfigurationfactory.cpp index 9cdaf53ab09..e4e938cf367 100644 --- a/src/plugins/remotelinux/remotelinuxrunconfigurationfactory.cpp +++ b/src/plugins/remotelinux/remotelinuxrunconfigurationfactory.cpp @@ -32,7 +32,6 @@ #include "remotelinux_constants.h" #include "remotelinuxdeployconfigurationfactory.h" #include "remotelinuxrunconfiguration.h" -#include "remotelinuxutils.h" #include #include diff --git a/src/plugins/remotelinux/remotelinuxrunconfigurationwidget.cpp b/src/plugins/remotelinux/remotelinuxrunconfigurationwidget.cpp index c31910d3add..8cc6c45283c 100644 --- a/src/plugins/remotelinux/remotelinuxrunconfigurationwidget.cpp +++ b/src/plugins/remotelinux/remotelinuxrunconfigurationwidget.cpp @@ -31,7 +31,6 @@ #include "remotelinuxrunconfiguration.h" #include "remotelinuxenvironmentreader.h" -#include "remotelinuxutils.h" #include #include diff --git a/src/plugins/remotelinux/remotelinuxruncontrol.cpp b/src/plugins/remotelinux/remotelinuxruncontrol.cpp index 3492cf3a731..554816cf585 100644 --- a/src/plugins/remotelinux/remotelinuxruncontrol.cpp +++ b/src/plugins/remotelinux/remotelinuxruncontrol.cpp @@ -30,7 +30,6 @@ #include "remotelinuxruncontrol.h" #include "remotelinuxrunconfiguration.h" -#include "remotelinuxutils.h" #include #include @@ -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); diff --git a/src/plugins/remotelinux/remotelinuxruncontrol.h b/src/plugins/remotelinux/remotelinuxruncontrol.h index 86f690d66a5..207644ca5ba 100644 --- a/src/plugins/remotelinux/remotelinuxruncontrol.h +++ b/src/plugins/remotelinux/remotelinuxruncontrol.h @@ -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); diff --git a/src/plugins/remotelinux/remotelinuxutils.cpp b/src/plugins/remotelinux/remotelinuxutils.cpp index 907d04e570e..2eb4518a6c1 100644 --- a/src/plugins/remotelinux/remotelinuxutils.cpp +++ b/src/plugins/remotelinux/remotelinuxutils.cpp @@ -29,20 +29,6 @@ **************************************************************************/ #include "remotelinuxutils.h" -#include "linuxdevice.h" - -#include - 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 diff --git a/src/plugins/remotelinux/remotelinuxutils.h b/src/plugins/remotelinux/remotelinuxutils.h index b8bbf3b7588..24d9c37488c 100644 --- a/src/plugins/remotelinux/remotelinuxutils.h +++ b/src/plugins/remotelinux/remotelinuxutils.h @@ -32,15 +32,11 @@ #include "remotelinux_export.h" -#include - namespace RemoteLinux { -class LinuxDevice; class REMOTELINUX_EXPORT RemoteLinuxUtils { public: - static QString killApplicationCommandLine(const QString &applicationFilePath); }; } // namespace RemoteLinux