diff --git a/src/plugins/android/androiddevice.cpp b/src/plugins/android/androiddevice.cpp index 83ee64d9401ff1a67cc5f885013244e983f0b0c0..42e698e04427aab72a0f0110e964a8a7611293a6 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<DeviceProcess> AndroidDevice::buildProcessList(const QString &listProcessesReply) const -{ - Q_UNUSED(listProcessesReply); - return QList<DeviceProcess>(); -} - } // namespace Internal } // namespace Android diff --git a/src/plugins/android/androiddevice.h b/src/plugins/android/androiddevice.h index f38f82cc1393b303008d7ee96eedda324c25217b..e4b8e28ce38f83bbc5dd3ae046b1046d2d7dd0d9 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<ProjectExplorer::DeviceProcess> 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 31b11975fd71a220147743beed30e4f6f6b1da0e..15c6fee7ea1371fa35310935e7126678da79b1eb 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<DeviceProcess> DesktopDevice::buildProcessList(const QString &listProcessesReply) const -{ - Q_UNUSED(listProcessesReply); - return QList<DeviceProcess>(); -} - } // namespace ProjectExplorer diff --git a/src/plugins/projectexplorer/devicesupport/desktopdevice.h b/src/plugins/projectexplorer/devicesupport/desktopdevice.h index bd852ab45cea8885bc9926e59b74f60f4f44b8c7..4fb3857ca8cb85d5b657d3429c03b14a97c48df5 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<DeviceProcess> 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 7553c5c29f8c7a59b4bcf7060a1ea93211838620..be2be74cfdb892c2130745fa4cd626aab601709f 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<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; diff --git a/src/plugins/projectexplorer/devicesupport/deviceusedportsgatherer.cpp b/src/plugins/projectexplorer/devicesupport/deviceusedportsgatherer.cpp index 8d57f9e22cff62e98c8964ba15dc41ffd95fee53..a97e1d95fc7fa115e2a5389e38d21e44de67b7f3 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<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(); } diff --git a/src/plugins/projectexplorer/devicesupport/deviceusedportsgatherer.h b/src/plugins/projectexplorer/devicesupport/deviceusedportsgatherer.h index f68dd6fa4d60c5d2c4e4be0370efef63c2088142..0ab94597cdde2ed6db832ab4ac7b7880fb7268e1 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<int> 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 13675b3dd08d1577ba13fb1d1fdf80c92b33ddda..5a9430b1d3f5509355f0fb90b51d9296faf3f038 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 f69480fb70a3b64cd2106b1b916654b76c659ebe..c20ae330b22bf356df76b73ab8d28ae2984a5898 100644 --- a/src/plugins/projectexplorer/devicesupport/idevice.h +++ b/src/plugins/projectexplorer/devicesupport/idevice.h @@ -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; diff --git a/src/plugins/projectexplorer/projectexplorer.pri b/src/plugins/projectexplorer/projectexplorer.pri index 8b464277e4e10981ce40d5357001e7d3aae907f1..b1df3996e2d9df0172f993134a2ab7ccf0c065f3 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 10234f3ab56e1ad4939698bfa476609101082ccd..d36076c1b506f2aa015081fcce8b6d1c860f5ce3 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 115f406c75f99e33b19e09b37e0a7e9772cf3e89..9071604230ca1e739c3deef172633a797e9470b2 100644 --- a/src/plugins/qmlprofiler/remotelinuxqmlprofilerrunner.cpp +++ b/src/plugins/qmlprofiler/remotelinuxqmlprofilerrunner.cpp @@ -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; } diff --git a/src/plugins/qnx/qnxconstants.h b/src/plugins/qnx/qnxconstants.h index 26c68cd835238d9d6c272105453d6c31f2140df1..ab5a2f4b4d9d47b26c85a9d44c5565ec8356dce4 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 766a06c9bf0d5283e1e98e9d47e9e09e9ecb1872..03a84db5d92d2c4e5a01dd6f0f5677321e85db9a 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 <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) diff --git a/src/plugins/qnx/qnxdeviceconfiguration.cpp b/src/plugins/qnx/qnxdeviceconfiguration.cpp index 1eb6c136d6716da7f2149c0c47fc1a1f5465ddc9..2c22a072372e11e95d7988ac1e3591ada02ac398 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<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); +} diff --git a/src/plugins/qnx/qnxdeviceconfiguration.h b/src/plugins/qnx/qnxdeviceconfiguration.h index 0a68f9a9c9e059e988cf887f089d9c06749540a9..fe5bc58b8b9b25668bd06672afc5b7139957cea1 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 5fba97eba0b5323407aa0a5fcf84a2bb701652e5..a113cb5e07e1a7f7afedcf2fbf63d1bf8f4a57da 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 f3cb262c56e80f7b3572009c607b415081468163..81940942ba74c0a3325b450288ddce2baeb46f35 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 <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()); } diff --git a/src/plugins/qnx/qnxutils.cpp b/src/plugins/qnx/qnxutils.cpp index d96b50649a08d298cceeff047bab7c23bd13b974..4ef95137c97f9a244050f2832571fc6bb7cdea87 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 82d63de84131308b515bb4273f507cfa5963495b..1195f87c5797abf511fd7095ec69afc10fded7bc 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 d0f0c662e1d2b7cbf39d746067a9e7dd959d5faf..b084ecdac61993dbdf17f86b3df9741e72dc4a3b 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<DeviceProcess> SymbianIDevice::buildProcessList(const QString &listProcessesReply) const -{ - Q_UNUSED(listProcessesReply); - return QList<DeviceProcess>(); -} - } // namespace qt4projectmanager diff --git a/src/plugins/qt4projectmanager/qt-s60/symbianidevice.h b/src/plugins/qt4projectmanager/qt-s60/symbianidevice.h index aaba2fe407fb22f2ef907036ed1c0bebcc0b2b8b..2a8ba273cf96ef6f2ba2d3086dadb3b040445b95 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<ProjectExplorer::DeviceProcess> 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 4a3b1d968f7594d1755360d37837dc2467e3149a..864e76d03380c612a9017bdfa82a7c402b8174a5 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("<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 -{ - 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); -} - -QString LinuxDevice::killProcessCommandLine(const DeviceProcess &process) const +DeviceProcessSupport::Ptr LinuxDevice::processSupport() const { - return QLatin1String("kill -9 ") + QString::number(process.pid); + return DeviceProcessSupport::Ptr(new LinuxDeviceProcessSupport); } -QList<DeviceProcess> LinuxDevice::buildProcessList(const QString &listProcessesReply) const +PortsGatheringMethod::Ptr LinuxDevice::portsGatheringMethod() 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 diff --git a/src/plugins/remotelinux/linuxdevice.h b/src/plugins/remotelinux/linuxdevice.h index 3d4a5f73294e024e5ae863f38a915e6d0c2c573d..60a05c85b813697018a2b3b04a09bd181f933dfa 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<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() {} diff --git a/src/plugins/remotelinux/remotelinuxdebugsupport.cpp b/src/plugins/remotelinux/remotelinuxdebugsupport.cpp index a0f57b283dff33c2c8b8f5dc58a5084d60bae8ca..baa5be50af1edb0485be27329a94f571422bb45c 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 <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; } diff --git a/src/plugins/remotelinux/remotelinuxrunconfigurationfactory.cpp b/src/plugins/remotelinux/remotelinuxrunconfigurationfactory.cpp index 9cdaf53ab0958f9027144e66c8c15b5f2311f9ff..e4e938cf367d095e0c01398d9a72580d5b477a8a 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 <projectexplorer/profileinformation.h> #include <projectexplorer/target.h> diff --git a/src/plugins/remotelinux/remotelinuxrunconfigurationwidget.cpp b/src/plugins/remotelinux/remotelinuxrunconfigurationwidget.cpp index c31910d3addf02b75e19b4b8812d5466ef2b66d6..8cc6c45283c9dad0c2df0a4c2c1f15bd77da74a2 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 <coreplugin/coreconstants.h> #include <coreplugin/icore.h> diff --git a/src/plugins/remotelinux/remotelinuxruncontrol.cpp b/src/plugins/remotelinux/remotelinuxruncontrol.cpp index 3492cf3a731124f56141496117548e27ef04c3e4..554816cf5855185a8259b11f62e84b4a2bc325a9 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 <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); diff --git a/src/plugins/remotelinux/remotelinuxruncontrol.h b/src/plugins/remotelinux/remotelinuxruncontrol.h index 86f690d66a507763c4f8cc8a5fc97ee6f4140ebd..207644ca5bafa3436f7ed8e305265ea1cdc9eaa9 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 907d04e570edc7cd689670e258d978927ef2452b..2eb4518a6c1fbda9279b544bdbada35b208eaf22 100644 --- a/src/plugins/remotelinux/remotelinuxutils.cpp +++ b/src/plugins/remotelinux/remotelinuxutils.cpp @@ -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 diff --git a/src/plugins/remotelinux/remotelinuxutils.h b/src/plugins/remotelinux/remotelinuxutils.h index b8bbf3b75883408939b33c407a7c540cae1c8225..24d9c37488c2658191b5a525361f5f3d74c0a16b 100644 --- a/src/plugins/remotelinux/remotelinuxutils.h +++ b/src/plugins/remotelinux/remotelinuxutils.h @@ -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