Use ProcessInfo instead of DeviceProcessItem

Remove DeviceProcessItem class.

Change-Id: I2fcac473dc12b47f50c329645f27d60619304e77
Reviewed-by: hjk <hjk@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
This commit is contained in:
Jarek Kobus
2022-02-24 18:42:47 +01:00
parent 87154986d2
commit 4bb4bc2a99
18 changed files with 108 additions and 289 deletions

View File

@@ -89,7 +89,6 @@
#include <projectexplorer/buildconfiguration.h> #include <projectexplorer/buildconfiguration.h>
#include <projectexplorer/buildmanager.h> #include <projectexplorer/buildmanager.h>
#include <projectexplorer/devicesupport/deviceprocessesdialog.h> #include <projectexplorer/devicesupport/deviceprocessesdialog.h>
#include <projectexplorer/devicesupport/deviceprocesslist.h>
#include <projectexplorer/itaskhandler.h> #include <projectexplorer/itaskhandler.h>
#include <projectexplorer/project.h> #include <projectexplorer/project.h>
#include <projectexplorer/projectexplorer.h> #include <projectexplorer/projectexplorer.h>
@@ -114,6 +113,7 @@
#include <utils/checkablemessagebox.h> #include <utils/checkablemessagebox.h>
#include <utils/fancymainwindow.h> #include <utils/fancymainwindow.h>
#include <utils/hostosinfo.h> #include <utils/hostosinfo.h>
#include <utils/processinfo.h>
#include <utils/proxyaction.h> #include <utils/proxyaction.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <utils/statuslabel.h> #include <utils/statuslabel.h>
@@ -606,7 +606,7 @@ public:
void extensionsInitialized(); void extensionsInitialized();
void aboutToShutdown(); void aboutToShutdown();
RunControl *attachToRunningProcess(Kit *kit, DeviceProcessItem process, bool contAfterAttach); RunControl *attachToRunningProcess(Kit *kit, const ProcessInfo &process, bool contAfterAttach);
void writeSettings() void writeSettings()
{ {
@@ -1659,16 +1659,16 @@ void DebuggerPluginPrivate::attachToRunningApplication()
IDevice::ConstPtr device = DeviceKitAspect::device(kit); IDevice::ConstPtr device = DeviceKitAspect::device(kit);
QTC_ASSERT(device, return); QTC_ASSERT(device, return);
DeviceProcessItem process = dlg->currentProcess(); const ProcessInfo processInfo = dlg->currentProcess();
if (device->type() == PE::DESKTOP_DEVICE_TYPE) { if (device->type() == PE::DESKTOP_DEVICE_TYPE) {
attachToRunningProcess(kit, process, false); attachToRunningProcess(kit, processInfo, false);
} else { } else {
auto runControl = new RunControl(ProjectExplorer::Constants::DEBUG_RUN_MODE); auto runControl = new RunControl(ProjectExplorer::Constants::DEBUG_RUN_MODE);
runControl->setKit(kit); runControl->setKit(kit);
//: %1: PID //: %1: PID
runControl->setDisplayName(tr("Process %1").arg(process.pid)); runControl->setDisplayName(tr("Process %1").arg(processInfo.processId));
auto debugger = new RemoteAttachRunner(runControl, ProcessHandle(process.pid)); auto debugger = new RemoteAttachRunner(runControl, ProcessHandle(processInfo.processId));
debugger->startRunControl(); debugger->startRunControl();
} }
} }
@@ -1693,23 +1693,23 @@ void DebuggerPluginPrivate::attachToUnstartedApplicationDialog()
} }
RunControl *DebuggerPluginPrivate::attachToRunningProcess(Kit *kit, RunControl *DebuggerPluginPrivate::attachToRunningProcess(Kit *kit,
DeviceProcessItem process, bool contAfterAttach) const ProcessInfo &processInfo, bool contAfterAttach)
{ {
QTC_ASSERT(kit, return nullptr); QTC_ASSERT(kit, return nullptr);
IDevice::ConstPtr device = DeviceKitAspect::device(kit); IDevice::ConstPtr device = DeviceKitAspect::device(kit);
QTC_ASSERT(device, return nullptr); QTC_ASSERT(device, return nullptr);
if (process.pid == 0) { if (processInfo.processId == 0) {
AsynchronousMessageBox::warning(tr("Warning"), tr("Cannot attach to process with PID 0")); AsynchronousMessageBox::warning(tr("Warning"), tr("Cannot attach to process with PID 0"));
return nullptr; return nullptr;
} }
const Abi tcAbi = ToolChainKitAspect::targetAbi(kit); const Abi tcAbi = ToolChainKitAspect::targetAbi(kit);
const bool isWindows = (tcAbi.os() == Abi::WindowsOS); const bool isWindows = (tcAbi.os() == Abi::WindowsOS);
if (isWindows && isWinProcessBeingDebugged(process.pid)) { if (isWindows && isWinProcessBeingDebugged(processInfo.processId)) {
AsynchronousMessageBox::warning( AsynchronousMessageBox::warning(
tr("Process Already Under Debugger Control"), tr("Process Already Under Debugger Control"),
tr("The process %1 is already under the control of a debugger.\n" tr("The process %1 is already under the control of a debugger.\n"
"%2 cannot attach to it.").arg(process.pid) "%2 cannot attach to it.").arg(processInfo.processId)
.arg(Core::Constants::IDE_DISPLAY_NAME)); .arg(Core::Constants::IDE_DISPLAY_NAME));
return nullptr; return nullptr;
} }
@@ -1723,10 +1723,10 @@ RunControl *DebuggerPluginPrivate::attachToRunningProcess(Kit *kit,
auto runControl = new RunControl(ProjectExplorer::Constants::DEBUG_RUN_MODE); auto runControl = new RunControl(ProjectExplorer::Constants::DEBUG_RUN_MODE);
runControl->setKit(kit); runControl->setKit(kit);
//: %1: PID //: %1: PID
runControl->setDisplayName(tr("Process %1").arg(process.pid)); runControl->setDisplayName(tr("Process %1").arg(processInfo.processId));
auto debugger = new DebuggerRunTool(runControl); auto debugger = new DebuggerRunTool(runControl);
debugger->setAttachPid(ProcessHandle(process.pid)); debugger->setAttachPid(ProcessHandle(processInfo.processId));
debugger->setInferiorExecutable(FilePath::fromString(process.exe)); debugger->setInferiorExecutable(FilePath::fromString(processInfo.executable));
debugger->setInferiorDevice(device); debugger->setInferiorDevice(device);
debugger->setStartMode(AttachToLocalProcess); debugger->setStartMode(AttachToLocalProcess);
debugger->setCloseMode(DetachAtClose); debugger->setCloseMode(DetachAtClose);

View File

@@ -42,7 +42,6 @@
#include <projectexplorer/buildconfiguration.h> #include <projectexplorer/buildconfiguration.h>
#include <projectexplorer/devicesupport/deviceprocessesdialog.h> #include <projectexplorer/devicesupport/deviceprocessesdialog.h>
#include <projectexplorer/devicesupport/deviceprocesslist.h>
#include <projectexplorer/environmentaspect.h> // For the environment #include <projectexplorer/environmentaspect.h> // For the environment
#include <projectexplorer/project.h> #include <projectexplorer/project.h>
#include <projectexplorer/projectexplorer.h> #include <projectexplorer/projectexplorer.h>

View File

@@ -51,6 +51,7 @@
#include <QFileDialog> #include <QFileDialog>
using namespace ProjectExplorer; using namespace ProjectExplorer;
using namespace Utils;
namespace Debugger { namespace Debugger {
namespace Internal { namespace Internal {
@@ -224,7 +225,7 @@ void UnstartedAppWatcherDialog::startWatching()
} }
} }
void UnstartedAppWatcherDialog::pidFound(const DeviceProcessItem &p) void UnstartedAppWatcherDialog::pidFound(const ProcessInfo &p)
{ {
setWaitingState(FoundState); setWaitingState(FoundState);
startStopTimer(false); startStopTimer(false);
@@ -256,16 +257,17 @@ void UnstartedAppWatcherDialog::startStopTimer(bool start)
void UnstartedAppWatcherDialog::findProcess() void UnstartedAppWatcherDialog::findProcess()
{ {
const QString &appName = m_pathChooser->filePath().normalizedPathName().toString(); const QString &appName = m_pathChooser->filePath().normalizedPathName().toString();
DeviceProcessItem fallback; ProcessInfo fallback;
foreach (const DeviceProcessItem &p, DeviceProcessList::localProcesses()) { const QList<ProcessInfo> processInfoList = ProcessInfo::processInfoList();
if (Utils::FileUtils::normalizedPathName(p.exe) == appName) { for (const ProcessInfo &processInfo : processInfoList) {
pidFound(p); if (Utils::FileUtils::normalizedPathName(processInfo.executable) == appName) {
pidFound(processInfo);
return; return;
} }
if (p.cmdLine.startsWith(appName)) if (processInfo.commandLine.startsWith(appName))
fallback = p; fallback = processInfo;
} }
if (fallback.pid != 0) if (fallback.processId != 0)
pidFound(fallback); pidFound(fallback);
} }
@@ -302,7 +304,7 @@ Kit *UnstartedAppWatcherDialog::currentKit() const
return m_kitChooser->currentKit(); return m_kitChooser->currentKit();
} }
DeviceProcessItem UnstartedAppWatcherDialog::currentProcess() const ProcessInfo UnstartedAppWatcherDialog::currentProcess() const
{ {
return m_process; return m_process;
} }

View File

@@ -28,7 +28,7 @@
#include <QDialog> #include <QDialog>
#include <QTimer> #include <QTimer>
#include <projectexplorer/devicesupport/deviceprocesslist.h> #include <utils/processinfo.h>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QLabel; class QLabel;
@@ -53,7 +53,7 @@ public:
explicit UnstartedAppWatcherDialog(QWidget *parent = nullptr); explicit UnstartedAppWatcherDialog(QWidget *parent = nullptr);
ProjectExplorer::Kit *currentKit() const; ProjectExplorer::Kit *currentKit() const;
ProjectExplorer::DeviceProcessItem currentProcess() const; Utils::ProcessInfo currentProcess() const;
bool hideOnAttach() const; bool hideOnAttach() const;
bool continueOnAttach() const; bool continueOnAttach() const;
void startWatching(); void startWatching();
@@ -65,7 +65,7 @@ signals:
private: private:
void selectExecutable(); void selectExecutable();
void pidFound(const ProjectExplorer::DeviceProcessItem &p); void pidFound(const Utils::ProcessInfo &p);
void startStopWatching(bool start); void startStopWatching(bool start);
void findProcess(); void findProcess();
void stopAndCheckExecutable(); void stopAndCheckExecutable();
@@ -89,7 +89,7 @@ private:
QCheckBox *m_hideOnAttachCheckBox; QCheckBox *m_hideOnAttachCheckBox;
QCheckBox *m_continueOnAttachCheckBox; QCheckBox *m_continueOnAttachCheckBox;
QPushButton *m_watchingPushButton; QPushButton *m_watchingPushButton;
ProjectExplorer::DeviceProcessItem m_process; Utils::ProcessInfo m_process;
QTimer m_timer; QTimer m_timer;
}; };

View File

@@ -25,12 +25,11 @@
#include "desktopprocesssignaloperation.h" #include "desktopprocesssignaloperation.h"
#include "localprocesslist.h"
#include <app/app_version.h> #include <app/app_version.h>
#include <utils/winutils.h> #include <utils/winutils.h>
#include <utils/fileutils.h> #include <utils/fileutils.h>
#include <utils/processinfo.h>
#include <QCoreApplication> #include <QCoreApplication>
#include <QDir> #include <QDir>
@@ -46,6 +45,8 @@
#include <signal.h> #include <signal.h>
#endif // else Q_OS_WIN #endif // else Q_OS_WIN
using namespace Utils;
namespace ProjectExplorer { namespace ProjectExplorer {
void DesktopProcessSignalOperation::killProcess(qint64 pid) void DesktopProcessSignalOperation::killProcess(qint64 pid)
@@ -57,9 +58,10 @@ void DesktopProcessSignalOperation::killProcess(qint64 pid)
void DesktopProcessSignalOperation::killProcess(const QString &filePath) void DesktopProcessSignalOperation::killProcess(const QString &filePath)
{ {
m_errorMessage.clear(); m_errorMessage.clear();
foreach (const DeviceProcessItem &process, Internal::LocalProcessList::getLocalProcesses()) { const QList<ProcessInfo> processInfoList = ProcessInfo::processInfoList();
if (process.cmdLine == filePath) for (const ProcessInfo &processInfo : processInfoList) {
killProcessSilently(process.pid); if (processInfo.commandLine == filePath)
killProcessSilently(processInfo.processId);
} }
emit finished(m_errorMessage); emit finished(m_errorMessage);
} }
@@ -74,9 +76,10 @@ void DesktopProcessSignalOperation::interruptProcess(qint64 pid)
void DesktopProcessSignalOperation::interruptProcess(const QString &filePath) void DesktopProcessSignalOperation::interruptProcess(const QString &filePath)
{ {
m_errorMessage.clear(); m_errorMessage.clear();
foreach (const DeviceProcessItem &process, Internal::LocalProcessList::getLocalProcesses()) { const QList<ProcessInfo> processInfoList = ProcessInfo::processInfoList();
if (process.cmdLine == filePath) for (const ProcessInfo &processInfo : processInfoList) {
interruptProcessSilently(process.pid); if (processInfo.commandLine == filePath)
interruptProcessSilently(processInfo.processId);
} }
emit finished(m_errorMessage); emit finished(m_errorMessage);
} }
@@ -105,7 +108,7 @@ void DesktopProcessSignalOperation::killProcessSilently(qint64 pid)
|PROCESS_DUP_HANDLE|PROCESS_TERMINATE|PROCESS_CREATE_THREAD|PROCESS_SUSPEND_RESUME; |PROCESS_DUP_HANDLE|PROCESS_TERMINATE|PROCESS_CREATE_THREAD|PROCESS_SUSPEND_RESUME;
if (const HANDLE handle = OpenProcess(rights, FALSE, DWORD(pid))) { if (const HANDLE handle = OpenProcess(rights, FALSE, DWORD(pid))) {
if (!TerminateProcess(handle, UINT(-1))) if (!TerminateProcess(handle, UINT(-1)))
appendMsgCannotKill(pid, Utils::winErrorMessage(GetLastError())); appendMsgCannotKill(pid, winErrorMessage(GetLastError()));
CloseHandle(handle); CloseHandle(handle);
} else { } else {
appendMsgCannotKill(pid, tr("Cannot open process.")); appendMsgCannotKill(pid, tr("Cannot open process."));
@@ -123,10 +126,10 @@ void DesktopProcessSignalOperation::interruptProcessSilently(qint64 pid)
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
enum SpecialInterrupt { NoSpecialInterrupt, Win32Interrupt, Win64Interrupt }; enum SpecialInterrupt { NoSpecialInterrupt, Win32Interrupt, Win64Interrupt };
bool is64BitSystem = Utils::is64BitWindowsSystem(); bool is64BitSystem = is64BitWindowsSystem();
SpecialInterrupt si = NoSpecialInterrupt; SpecialInterrupt si = NoSpecialInterrupt;
if (is64BitSystem) if (is64BitSystem)
si = Utils::is64BitWindowsBinary(m_debuggerCommand) ? Win64Interrupt : Win32Interrupt; si = is64BitWindowsBinary(m_debuggerCommand) ? Win64Interrupt : Win32Interrupt;
/* /*
Windows 64 bit has a 32 bit subsystem (WOW64) which makes it possible to run a Windows 64 bit has a 32 bit subsystem (WOW64) which makes it possible to run a
32 bit application inside a 64 bit environment. 32 bit application inside a 64 bit environment.
@@ -164,18 +167,18 @@ GDB 32bit | Api | Api | N/A | Win32
inferior = OpenProcess(rights, FALSE, pid); inferior = OpenProcess(rights, FALSE, pid);
if (inferior == NULL) { if (inferior == NULL) {
appendMsgCannotInterrupt(pid, tr("Cannot open process: %1") appendMsgCannotInterrupt(pid, tr("Cannot open process: %1")
+ Utils::winErrorMessage(GetLastError())); + winErrorMessage(GetLastError()));
break; break;
} }
bool creatorIs64Bit = Utils::is64BitWindowsBinary( bool creatorIs64Bit = is64BitWindowsBinary(
Utils::FilePath::fromUserInput(QCoreApplication::applicationFilePath())); FilePath::fromUserInput(QCoreApplication::applicationFilePath()));
if (!is64BitSystem if (!is64BitSystem
|| si == NoSpecialInterrupt || si == NoSpecialInterrupt
|| (si == Win64Interrupt && creatorIs64Bit) || (si == Win64Interrupt && creatorIs64Bit)
|| (si == Win32Interrupt && !creatorIs64Bit)) { || (si == Win32Interrupt && !creatorIs64Bit)) {
if (!DebugBreakProcess(inferior)) { if (!DebugBreakProcess(inferior)) {
appendMsgCannotInterrupt(pid, tr("DebugBreakProcess failed:") appendMsgCannotInterrupt(pid, tr("DebugBreakProcess failed:")
+ QLatin1Char(' ') + Utils::winErrorMessage(GetLastError())); + QLatin1Char(' ') + winErrorMessage(GetLastError()));
} }
} else if (si == Win32Interrupt || si == Win64Interrupt) { } else if (si == Win32Interrupt || si == Win64Interrupt) {
QString executable = QCoreApplication::applicationDirPath(); QString executable = QCoreApplication::applicationDirPath();

View File

@@ -30,6 +30,7 @@
#include <utils/fancylineedit.h> #include <utils/fancylineedit.h>
#include <utils/itemviews.h> #include <utils/itemviews.h>
#include <utils/processinfo.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <QDialogButtonBox> #include <QDialogButtonBox>
@@ -99,7 +100,7 @@ public:
void handleProcessListUpdated(); void handleProcessListUpdated();
void handleProcessKilled(); void handleProcessKilled();
void updateButtons(); void updateButtons();
DeviceProcessItem selectedProcess() const; ProcessInfo selectedProcess() const;
QDialog *q; QDialog *q;
DeviceProcessList *processList; DeviceProcessList *processList;
@@ -279,11 +280,11 @@ void DeviceProcessesDialogPrivate::updateButtons()
errorText->setVisible(!errorText->document()->isEmpty()); errorText->setVisible(!errorText->document()->isEmpty());
} }
DeviceProcessItem DeviceProcessesDialogPrivate::selectedProcess() const ProcessInfo DeviceProcessesDialogPrivate::selectedProcess() const
{ {
const QModelIndexList indexes = procView->selectionModel()->selectedIndexes(); const QModelIndexList indexes = procView->selectionModel()->selectedIndexes();
if (indexes.empty() || !processList) if (indexes.empty() || !processList)
return DeviceProcessItem(); return ProcessInfo();
return processList->at(proxyModel.mapToSource(indexes.first()).row()); return processList->at(proxyModel.mapToSource(indexes.first()).row());
} }
@@ -352,7 +353,7 @@ void DeviceProcessesDialog::showAllDevices()
d->updateDevice(); d->updateDevice();
} }
DeviceProcessItem DeviceProcessesDialog::currentProcess() const ProcessInfo DeviceProcessesDialog::currentProcess() const
{ {
return d->selectedProcess(); return d->selectedProcess();
} }

View File

@@ -33,9 +33,10 @@
#include <memory> #include <memory>
namespace Utils { class ProcessInfo; }
namespace ProjectExplorer { namespace ProjectExplorer {
class DeviceProcessItem;
class KitChooser; class KitChooser;
namespace Internal { class DeviceProcessesDialogPrivate; } namespace Internal { class DeviceProcessesDialogPrivate; }
@@ -52,7 +53,7 @@ public:
void setDevice(const IDevice::ConstPtr &device); void setDevice(const IDevice::ConstPtr &device);
void showAllDevices(); void showAllDevices();
DeviceProcessItem currentProcess() const; Utils::ProcessInfo currentProcess() const;
KitChooser *kitChooser() const; KitChooser *kitChooser() const;
void logMessage(const QString &line); void logMessage(const QString &line);
DeviceProcessesDialog(KitChooser *chooser, QWidget *parent); DeviceProcessesDialog(KitChooser *chooser, QWidget *parent);

View File

@@ -24,11 +24,11 @@
****************************************************************************/ ****************************************************************************/
#include "deviceprocesslist.h" #include "deviceprocesslist.h"
#include "localprocesslist.h"
#include <utils/fileutils.h>
#include <utils/processinfo.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <utils/treemodel.h> #include <utils/treemodel.h>
#include <utils/fileutils.h>
using namespace Utils; using namespace Utils;
@@ -40,12 +40,12 @@ enum State { Inactive, Listing, Killing };
class DeviceProcessTreeItem : public TreeItem class DeviceProcessTreeItem : public TreeItem
{ {
public: public:
DeviceProcessTreeItem(const DeviceProcessItem &p, Qt::ItemFlags f) : process(p), fl(f) {} DeviceProcessTreeItem(const ProcessInfo &p, Qt::ItemFlags f) : process(p), fl(f) {}
QVariant data(int column, int role) const final; QVariant data(int column, int role) const final;
Qt::ItemFlags flags(int) const final { return fl; } Qt::ItemFlags flags(int) const final { return fl; }
DeviceProcessItem process; ProcessInfo process;
Qt::ItemFlags fl; Qt::ItemFlags fl;
}; };
@@ -88,14 +88,14 @@ void DeviceProcessList::update()
doUpdate(); doUpdate();
} }
void DeviceProcessList::reportProcessListUpdated(const QList<DeviceProcessItem> &processes) void DeviceProcessList::reportProcessListUpdated(const QList<ProcessInfo> &processes)
{ {
QTC_ASSERT(d->state == Listing, return); QTC_ASSERT(d->state == Listing, return);
setFinished(); setFinished();
d->model.clear(); d->model.clear();
for (const DeviceProcessItem &process : processes) { for (const ProcessInfo &process : processes) {
Qt::ItemFlags fl; Qt::ItemFlags fl;
if (process.pid != d->ownPid) if (process.processId != d->ownPid)
fl = Qt::ItemIsEnabled | Qt::ItemIsSelectable; fl = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
d->model.rootItem()->appendChild(new DeviceProcessTreeItem(process, fl)); d->model.rootItem()->appendChild(new DeviceProcessTreeItem(process, fl));
} }
@@ -125,7 +125,7 @@ void DeviceProcessList::reportProcessKilled()
emit processKilled(); emit processKilled();
} }
DeviceProcessItem DeviceProcessList::at(int row) const ProcessInfo DeviceProcessList::at(int row) const
{ {
return d->model.rootItem()->childAt(row)->process; return d->model.rootItem()->childAt(row)->process;
} }
@@ -139,9 +139,9 @@ QVariant DeviceProcessTreeItem::data(int column, int role) const
{ {
if (role == Qt::DisplayRole || role == Qt::ToolTipRole) { if (role == Qt::DisplayRole || role == Qt::ToolTipRole) {
if (column == 0) if (column == 0)
return process.pid ? process.pid : QVariant(); return process.processId ? process.processId : QVariant();
else else
return process.cmdLine; return process.commandLine;
} }
return QVariant(); return QVariant();
} }
@@ -163,18 +163,4 @@ void DeviceProcessList::reportError(const QString &message)
emit error(message); emit error(message);
} }
QList<DeviceProcessItem> DeviceProcessList::localProcesses()
{
return LocalProcessList::getLocalProcesses();
}
bool DeviceProcessItem::operator <(const DeviceProcessItem &other) const
{
if (pid != other.pid)
return pid < other.pid;
if (exe != other.exe)
return exe < other.exe;
return cmdLine < other.cmdLine;
}
} // namespace ProjectExplorer } // namespace ProjectExplorer

View File

@@ -32,20 +32,12 @@
#include <memory> #include <memory>
namespace Utils { class ProcessInfo; }
namespace ProjectExplorer { namespace ProjectExplorer {
namespace Internal { class DeviceProcessListPrivate; } namespace Internal { class DeviceProcessListPrivate; }
class PROJECTEXPLORER_EXPORT DeviceProcessItem
{
public:
bool operator<(const DeviceProcessItem &other) const;
qint64 pid = 0;
QString cmdLine;
QString exe;
};
class PROJECTEXPLORER_EXPORT DeviceProcessList : public QObject class PROJECTEXPLORER_EXPORT DeviceProcessList : public QObject
{ {
Q_OBJECT Q_OBJECT
@@ -58,11 +50,9 @@ public:
void killProcess(int row); void killProcess(int row);
void setOwnPid(qint64 pid); void setOwnPid(qint64 pid);
DeviceProcessItem at(int row) const; Utils::ProcessInfo at(int row) const;
QAbstractItemModel *model() const; QAbstractItemModel *model() const;
static QList<DeviceProcessItem> localProcesses();
signals: signals:
void processListUpdated(); void processListUpdated();
void error(const QString &errorMsg); void error(const QString &errorMsg);
@@ -71,13 +61,13 @@ signals:
protected: protected:
void reportError(const QString &message); void reportError(const QString &message);
void reportProcessKilled(); void reportProcessKilled();
void reportProcessListUpdated(const QList<DeviceProcessItem> &processes); void reportProcessListUpdated(const QList<Utils::ProcessInfo> &processes);
IDevice::ConstPtr device() const; IDevice::ConstPtr device() const;
private: private:
virtual void doUpdate() = 0; virtual void doUpdate() = 0;
virtual void doKillProcess(const DeviceProcessItem &process) = 0; virtual void doKillProcess(const Utils::ProcessInfo &process) = 0;
void setFinished(); void setFinished();

View File

@@ -25,204 +25,42 @@
#include "localprocesslist.h" #include "localprocesslist.h"
#include <utils/qtcprocess.h> #include <utils/processinfo.h>
#include <QLibrary>
#include <QTimer> #include <QTimer>
#ifdef Q_OS_UNIX #if defined(Q_OS_UNIX)
#include <QDir>
#include <signal.h>
#include <errno.h>
#include <string.h>
#include <unistd.h> #include <unistd.h>
#elif defined(Q_OS_WIN)
#include <windows.h>
#endif #endif
#ifdef Q_OS_WIN using namespace Utils;
#include <windows.h>
#include <utils/winutils.h>
#include <tlhelp32.h>
#include <psapi.h>
#endif
namespace ProjectExplorer { namespace ProjectExplorer {
namespace Internal { namespace Internal {
#ifdef Q_OS_WIN
LocalProcessList::LocalProcessList(const IDevice::ConstPtr &device, QObject *parent)
: DeviceProcessList(device, parent)
{
setOwnPid(GetCurrentProcessId());
}
QList<DeviceProcessItem> LocalProcessList::getLocalProcesses()
{
QList<DeviceProcessItem> processes;
PROCESSENTRY32 pe;
pe.dwSize = sizeof(PROCESSENTRY32);
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (snapshot == INVALID_HANDLE_VALUE)
return processes;
for (bool hasNext = Process32First(snapshot, &pe); hasNext; hasNext = Process32Next(snapshot, &pe)) {
DeviceProcessItem p;
p.pid = pe.th32ProcessID;
// Image has the absolute path, but can fail.
const QString image = Utils::imageName(pe.th32ProcessID);
p.exe = p.cmdLine = image.isEmpty() ?
QString::fromWCharArray(pe.szExeFile) :
image;
processes << p;
}
CloseHandle(snapshot);
return processes;
}
#endif //Q_OS_WIN
#ifdef Q_OS_UNIX
LocalProcessList::LocalProcessList(const IDevice::ConstPtr &device, QObject *parent) LocalProcessList::LocalProcessList(const IDevice::ConstPtr &device, QObject *parent)
: DeviceProcessList(device, parent) : DeviceProcessList(device, parent)
{ {
#if defined(Q_OS_UNIX)
setOwnPid(getpid()); setOwnPid(getpid());
#elif defined(Q_OS_WIN)
setOwnPid(GetCurrentProcessId());
#endif
} }
static bool isUnixProcessId(const QString &procname) void LocalProcessList::doKillProcess(const ProcessInfo &processInfo)
{
for (int i = 0; i != procname.size(); ++i)
if (!procname.at(i).isDigit())
return false;
return true;
}
// Determine UNIX processes by reading "/proc". Default to ps if
// it does not exist
static const char procDirC[] = "/proc/";
static QList<DeviceProcessItem> getLocalProcessesUsingProc(const QDir &procDir)
{
QList<DeviceProcessItem> processes;
const QString procDirPath = QLatin1String(procDirC);
const QStringList procIds = procDir.entryList();
for (const QString &procId : procIds) {
if (!isUnixProcessId(procId))
continue;
DeviceProcessItem proc;
proc.pid = procId.toInt();
const QString root = procDirPath + procId;
const QFile exeFile(root + QLatin1String("/exe"));
proc.exe = exeFile.symLinkTarget();
QFile cmdLineFile(root + QLatin1String("/cmdline"));
if (cmdLineFile.open(QIODevice::ReadOnly)) { // process may have exited
const QList<QByteArray> tokens = cmdLineFile.readAll().split('\0');
if (!tokens.isEmpty()) {
if (proc.exe.isEmpty())
proc.exe = QString::fromLocal8Bit(tokens.front());
for (const QByteArray &t : tokens) {
if (!proc.cmdLine.isEmpty())
proc.cmdLine.append(QLatin1Char(' '));
proc.cmdLine.append(QString::fromLocal8Bit(t));
}
}
}
if (proc.exe.isEmpty()) {
QFile statFile(root + QLatin1String("/stat"));
if (!statFile.open(QIODevice::ReadOnly)) {
const QStringList data = QString::fromLocal8Bit(statFile.readAll()).split(QLatin1Char(' '));
if (data.size() < 2)
continue;
proc.exe = data.at(1);
proc.cmdLine = data.at(1); // PPID is element 3
if (proc.exe.startsWith(QLatin1Char('(')) && proc.exe.endsWith(QLatin1Char(')'))) {
proc.exe.truncate(proc.exe.size() - 1);
proc.exe.remove(0, 1);
}
}
}
if (!proc.exe.isEmpty())
processes.push_back(proc);
}
return processes;
}
// Determine UNIX processes by running ps
static QMap<qint64, QString> getLocalProcessDataUsingPs(const QString &column)
{
QMap<qint64, QString> result;
Utils::QtcProcess psProcess;
psProcess.setCommand({"ps", {"-e", "-o", "pid," + column}});
psProcess.start();
if (psProcess.waitForStarted()) {
QByteArray output;
if (psProcess.readDataFromProcess(30, &output, nullptr, false)) {
// Split "457 /Users/foo.app arg1 arg2"
const QStringList lines = QString::fromLocal8Bit(output).split(QLatin1Char('\n'));
const int lineCount = lines.size();
const QChar blank = QLatin1Char(' ');
for (int l = 1; l < lineCount; l++) { // Skip header
const QString line = lines.at(l).trimmed();
const int pidSep = line.indexOf(blank);
const qint64 pid = line.left(pidSep).toLongLong();
result[pid] = line.mid(pidSep + 1);
}
}
}
return result;
}
static QList<DeviceProcessItem> getLocalProcessesUsingPs()
{
QList<DeviceProcessItem> processes;
// cmdLines are full command lines, usually with absolute path,
// exeNames only the file part of the executable's path.
const QMap<qint64, QString> exeNames = getLocalProcessDataUsingPs("comm");
const QMap<qint64, QString> cmdLines = getLocalProcessDataUsingPs("args");
for (auto it = exeNames.begin(), end = exeNames.end(); it != end; ++it) {
const qint64 pid = it.key();
if (pid <= 0)
continue;
const QString cmdLine = cmdLines.value(pid);
if (cmdLines.isEmpty())
continue;
const QString exeName = it.value();
if (exeName.isEmpty())
continue;
const int pos = cmdLine.indexOf(exeName);
if (pos == -1)
continue;
processes.append({pid, cmdLine, cmdLine.left(pos + exeName.size())});
}
return processes;
}
QList<DeviceProcessItem> LocalProcessList::getLocalProcesses()
{
const QDir procDir = QDir(QLatin1String(procDirC));
return procDir.exists() ? getLocalProcessesUsingProc(procDir) : getLocalProcessesUsingPs();
}
#endif // QT_OS_UNIX
void LocalProcessList::doKillProcess(const DeviceProcessItem &process)
{ {
DeviceProcessSignalOperation::Ptr signalOperation = device()->signalOperation(); DeviceProcessSignalOperation::Ptr signalOperation = device()->signalOperation();
connect(signalOperation.data(), &DeviceProcessSignalOperation::finished, connect(signalOperation.data(), &DeviceProcessSignalOperation::finished,
this, &LocalProcessList::reportDelayedKillStatus); this, &LocalProcessList::reportDelayedKillStatus);
signalOperation->killProcess(process.pid); signalOperation->killProcess(processInfo.processId);
} }
void LocalProcessList::handleUpdate() void LocalProcessList::handleUpdate()
{ {
reportProcessListUpdated(getLocalProcesses()); reportProcessListUpdated(ProcessInfo::processInfoList());
} }
void LocalProcessList::doUpdate() void LocalProcessList::doUpdate()

View File

@@ -37,11 +37,9 @@ class LocalProcessList : public DeviceProcessList
public: public:
explicit LocalProcessList(const IDevice::ConstPtr &device, QObject *parent = nullptr); explicit LocalProcessList(const IDevice::ConstPtr &device, QObject *parent = nullptr);
static QList<DeviceProcessItem> getLocalProcesses();
private: private:
void doUpdate() override; void doUpdate() override;
void doKillProcess(const DeviceProcessItem &process) override; void doKillProcess(const Utils::ProcessInfo &process) override;
private: private:
void handleUpdate(); void handleUpdate();

View File

@@ -28,10 +28,12 @@
#include "idevice.h" #include "idevice.h"
#include <ssh/sshremoteprocessrunner.h> #include <ssh/sshremoteprocessrunner.h>
#include <utils/qtcassert.h>
#include <utils/fileutils.h> #include <utils/fileutils.h>
#include <utils/processinfo.h>
#include <utils/qtcassert.h>
using namespace QSsh; using namespace QSsh;
using namespace Utils;
namespace ProjectExplorer { namespace ProjectExplorer {
@@ -58,13 +60,13 @@ void SshDeviceProcessList::doUpdate()
d->process.run(listProcessesCommandLine(), device()->sshParameters()); d->process.run(listProcessesCommandLine(), device()->sshParameters());
} }
void SshDeviceProcessList::doKillProcess(const DeviceProcessItem &process) void SshDeviceProcessList::doKillProcess(const ProcessInfo &process)
{ {
d->signalOperation = device()->signalOperation(); d->signalOperation = device()->signalOperation();
QTC_ASSERT(d->signalOperation, return); QTC_ASSERT(d->signalOperation, return);
connect(d->signalOperation.data(), &DeviceProcessSignalOperation::finished, connect(d->signalOperation.data(), &DeviceProcessSignalOperation::finished,
this, &SshDeviceProcessList::handleKillProcessFinished); this, &SshDeviceProcessList::handleKillProcessFinished);
d->signalOperation->killProcess(process.pid); d->signalOperation->killProcess(process.processId);
} }
void SshDeviceProcessList::handleConnectionError() void SshDeviceProcessList::handleConnectionError()

View File

@@ -44,10 +44,10 @@ private:
void handleKillProcessFinished(const QString &errorString); void handleKillProcessFinished(const QString &errorString);
virtual QString listProcessesCommandLine() const = 0; virtual QString listProcessesCommandLine() const = 0;
virtual QList<DeviceProcessItem> buildProcessList(const QString &listProcessesReply) const = 0; virtual QList<Utils::ProcessInfo> buildProcessList(const QString &listProcessesReply) const = 0;
void doUpdate() override; void doUpdate() override;
void doKillProcess(const DeviceProcessItem &process) override; void doKillProcess(const Utils::ProcessInfo &process) override;
void handleProcessError(const QString &errorMessage); void handleProcessError(const QString &errorMessage);
void setFinished(); void setFinished();

View File

@@ -38,7 +38,6 @@
#include <debugger/debuggerruncontrol.h> #include <debugger/debuggerruncontrol.h>
#include <projectexplorer/devicesupport/deviceprocessesdialog.h> #include <projectexplorer/devicesupport/deviceprocessesdialog.h>
#include <projectexplorer/devicesupport/deviceprocesslist.h>
#include <projectexplorer/devicesupport/deviceusedportsgatherer.h> #include <projectexplorer/devicesupport/deviceusedportsgatherer.h>
#include <projectexplorer/kit.h> #include <projectexplorer/kit.h>
#include <projectexplorer/kitchooser.h> #include <projectexplorer/kitchooser.h>
@@ -55,6 +54,7 @@
#include <utils/pathchooser.h> #include <utils/pathchooser.h>
#include <utils/portlist.h> #include <utils/portlist.h>
#include <utils/processinfo.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <utils/qtcprocess.h> #include <utils/qtcprocess.h>
@@ -244,8 +244,7 @@ void QnxAttachDebugSupport::showProcessesDialog()
if (!runConfig) if (!runConfig)
return; return;
DeviceProcessItem process = dlg.currentProcess(); const int pid = dlg.currentProcess().processId;
const int pid = process.pid;
// QString projectSourceDirectory = dlg.projectSource(); // QString projectSourceDirectory = dlg.projectSource();
FilePath localExecutable = dlg.localExecutable(); FilePath localExecutable = dlg.localExecutable();
if (localExecutable.isEmpty()) { if (localExecutable.isEmpty()) {

View File

@@ -27,12 +27,14 @@
#include <utils/algorithm.h> #include <utils/algorithm.h>
#include <utils/fileutils.h> #include <utils/fileutils.h>
#include <utils/processinfo.h>
#include <QRegularExpression> #include <QRegularExpression>
#include <QStringList> #include <QStringList>
using namespace Qnx; using namespace Qnx;
using namespace Qnx::Internal; using namespace Qnx::Internal;
using namespace Utils;
QnxDeviceProcessList::QnxDeviceProcessList( QnxDeviceProcessList::QnxDeviceProcessList(
const ProjectExplorer::IDevice::ConstPtr &device, QObject *parent) const ProjectExplorer::IDevice::ConstPtr &device, QObject *parent)
@@ -45,10 +47,9 @@ QString QnxDeviceProcessList::listProcessesCommandLine() const
return QLatin1String("pidin -F '%a %A {/%n}'"); return QLatin1String("pidin -F '%a %A {/%n}'");
} }
QList<ProjectExplorer::DeviceProcessItem> QnxDeviceProcessList::buildProcessList( QList<ProcessInfo> QnxDeviceProcessList::buildProcessList(const QString &listProcessesReply) const
const QString &listProcessesReply) const
{ {
QList<ProjectExplorer::DeviceProcessItem> processes; QList<ProcessInfo> processes;
QStringList lines = listProcessesReply.split(QLatin1Char('\n')); QStringList lines = listProcessesReply.split(QLatin1Char('\n'));
if (lines.isEmpty()) if (lines.isEmpty())
return processes; return processes;
@@ -64,10 +65,10 @@ QList<ProjectExplorer::DeviceProcessItem> QnxDeviceProcessList::buildProcessList
const int pid = captures[1].toInt(); const int pid = captures[1].toInt();
const QString args = captures[2]; const QString args = captures[2];
const QString exe = captures[3]; const QString exe = captures[3];
ProjectExplorer::DeviceProcessItem deviceProcess; ProcessInfo deviceProcess;
deviceProcess.pid = pid; deviceProcess.processId = pid;
deviceProcess.exe = exe.trimmed(); deviceProcess.executable = exe.trimmed();
deviceProcess.cmdLine = args.trimmed(); deviceProcess.commandLine = args.trimmed();
processes.append(deviceProcess); processes.append(deviceProcess);
} }
} }

View File

@@ -40,8 +40,7 @@ public:
private: private:
QString listProcessesCommandLine() const override; QString listProcessesCommandLine() const override;
QList<ProjectExplorer::DeviceProcessItem> buildProcessList( QList<Utils::ProcessInfo> buildProcessList(const QString &listProcessesReply) const override;
const QString &listProcessesReply) const override;
}; };
} // namespace Internal } // namespace Internal

View File

@@ -48,6 +48,7 @@
#include <utils/environment.h> #include <utils/environment.h>
#include <utils/hostosinfo.h> #include <utils/hostosinfo.h>
#include <utils/port.h> #include <utils/port.h>
#include <utils/processinfo.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <utils/stringutils.h> #include <utils/stringutils.h>
#include <utils/temporaryfile.h> #include <utils/temporaryfile.h>
@@ -100,12 +101,12 @@ private:
"done").arg(QLatin1String(Delimiter0)).arg(QLatin1String(Delimiter1)); "done").arg(QLatin1String(Delimiter0)).arg(QLatin1String(Delimiter1));
} }
QList<DeviceProcessItem> buildProcessList(const QString &listProcessesReply) const override QList<ProcessInfo> buildProcessList(const QString &listProcessesReply) const override
{ {
QList<DeviceProcessItem> processes; QList<ProcessInfo> processes;
const QStringList lines = listProcessesReply.split(QString::fromLatin1(Delimiter0) const QStringList lines = listProcessesReply.split(QString::fromLatin1(Delimiter0)
+ QString::fromLatin1(Delimiter1), Qt::SkipEmptyParts); + QString::fromLatin1(Delimiter1), Qt::SkipEmptyParts);
foreach (const QString &line, lines) { for (const QString &line : lines) {
const QStringList elements = line.split(QLatin1Char('\n')); const QStringList elements = line.split(QLatin1Char('\n'));
if (elements.count() < 4) { if (elements.count() < 4) {
qDebug("%s: Expected four list elements, got %d. Line was '%s'.", Q_FUNC_INFO, qDebug("%s: Expected four list elements, got %d. Line was '%s'.", Q_FUNC_INFO,
@@ -132,10 +133,10 @@ private:
+ QLatin1Char(']'); + QLatin1Char(']');
} }
DeviceProcessItem process; ProcessInfo process;
process.pid = pid; process.processId = pid;
process.cmdLine = command; process.commandLine = command;
process.exe = elements.at(3); process.executable = elements.at(3);
processes.append(process); processes.append(process);
} }

View File

@@ -31,7 +31,6 @@
#include <projectexplorer/devicesupport/desktopprocesssignaloperation.h> #include <projectexplorer/devicesupport/desktopprocesssignaloperation.h>
#include <projectexplorer/devicesupport/devicemanager.h> #include <projectexplorer/devicesupport/devicemanager.h>
#include <projectexplorer/devicesupport/deviceprocesslist.h>
#include <projectexplorer/projectexplorerconstants.h> #include <projectexplorer/projectexplorerconstants.h>
#include <qtsupport/qtversionmanager.h> #include <qtsupport/qtversionmanager.h>