forked from qt-creator/qt-creator
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:
@@ -89,7 +89,6 @@
|
||||
#include <projectexplorer/buildconfiguration.h>
|
||||
#include <projectexplorer/buildmanager.h>
|
||||
#include <projectexplorer/devicesupport/deviceprocessesdialog.h>
|
||||
#include <projectexplorer/devicesupport/deviceprocesslist.h>
|
||||
#include <projectexplorer/itaskhandler.h>
|
||||
#include <projectexplorer/project.h>
|
||||
#include <projectexplorer/projectexplorer.h>
|
||||
@@ -114,6 +113,7 @@
|
||||
#include <utils/checkablemessagebox.h>
|
||||
#include <utils/fancymainwindow.h>
|
||||
#include <utils/hostosinfo.h>
|
||||
#include <utils/processinfo.h>
|
||||
#include <utils/proxyaction.h>
|
||||
#include <utils/qtcassert.h>
|
||||
#include <utils/statuslabel.h>
|
||||
@@ -606,7 +606,7 @@ public:
|
||||
void extensionsInitialized();
|
||||
void aboutToShutdown();
|
||||
|
||||
RunControl *attachToRunningProcess(Kit *kit, DeviceProcessItem process, bool contAfterAttach);
|
||||
RunControl *attachToRunningProcess(Kit *kit, const ProcessInfo &process, bool contAfterAttach);
|
||||
|
||||
void writeSettings()
|
||||
{
|
||||
@@ -1659,16 +1659,16 @@ void DebuggerPluginPrivate::attachToRunningApplication()
|
||||
IDevice::ConstPtr device = DeviceKitAspect::device(kit);
|
||||
QTC_ASSERT(device, return);
|
||||
|
||||
DeviceProcessItem process = dlg->currentProcess();
|
||||
const ProcessInfo processInfo = dlg->currentProcess();
|
||||
|
||||
if (device->type() == PE::DESKTOP_DEVICE_TYPE) {
|
||||
attachToRunningProcess(kit, process, false);
|
||||
attachToRunningProcess(kit, processInfo, false);
|
||||
} else {
|
||||
auto runControl = new RunControl(ProjectExplorer::Constants::DEBUG_RUN_MODE);
|
||||
runControl->setKit(kit);
|
||||
//: %1: PID
|
||||
runControl->setDisplayName(tr("Process %1").arg(process.pid));
|
||||
auto debugger = new RemoteAttachRunner(runControl, ProcessHandle(process.pid));
|
||||
runControl->setDisplayName(tr("Process %1").arg(processInfo.processId));
|
||||
auto debugger = new RemoteAttachRunner(runControl, ProcessHandle(processInfo.processId));
|
||||
debugger->startRunControl();
|
||||
}
|
||||
}
|
||||
@@ -1693,23 +1693,23 @@ void DebuggerPluginPrivate::attachToUnstartedApplicationDialog()
|
||||
}
|
||||
|
||||
RunControl *DebuggerPluginPrivate::attachToRunningProcess(Kit *kit,
|
||||
DeviceProcessItem process, bool contAfterAttach)
|
||||
const ProcessInfo &processInfo, bool contAfterAttach)
|
||||
{
|
||||
QTC_ASSERT(kit, return nullptr);
|
||||
IDevice::ConstPtr device = DeviceKitAspect::device(kit);
|
||||
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"));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const Abi tcAbi = ToolChainKitAspect::targetAbi(kit);
|
||||
const bool isWindows = (tcAbi.os() == Abi::WindowsOS);
|
||||
if (isWindows && isWinProcessBeingDebugged(process.pid)) {
|
||||
if (isWindows && isWinProcessBeingDebugged(processInfo.processId)) {
|
||||
AsynchronousMessageBox::warning(
|
||||
tr("Process Already Under Debugger Control"),
|
||||
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));
|
||||
return nullptr;
|
||||
}
|
||||
@@ -1723,10 +1723,10 @@ RunControl *DebuggerPluginPrivate::attachToRunningProcess(Kit *kit,
|
||||
auto runControl = new RunControl(ProjectExplorer::Constants::DEBUG_RUN_MODE);
|
||||
runControl->setKit(kit);
|
||||
//: %1: PID
|
||||
runControl->setDisplayName(tr("Process %1").arg(process.pid));
|
||||
runControl->setDisplayName(tr("Process %1").arg(processInfo.processId));
|
||||
auto debugger = new DebuggerRunTool(runControl);
|
||||
debugger->setAttachPid(ProcessHandle(process.pid));
|
||||
debugger->setInferiorExecutable(FilePath::fromString(process.exe));
|
||||
debugger->setAttachPid(ProcessHandle(processInfo.processId));
|
||||
debugger->setInferiorExecutable(FilePath::fromString(processInfo.executable));
|
||||
debugger->setInferiorDevice(device);
|
||||
debugger->setStartMode(AttachToLocalProcess);
|
||||
debugger->setCloseMode(DetachAtClose);
|
||||
|
||||
@@ -42,7 +42,6 @@
|
||||
|
||||
#include <projectexplorer/buildconfiguration.h>
|
||||
#include <projectexplorer/devicesupport/deviceprocessesdialog.h>
|
||||
#include <projectexplorer/devicesupport/deviceprocesslist.h>
|
||||
#include <projectexplorer/environmentaspect.h> // For the environment
|
||||
#include <projectexplorer/project.h>
|
||||
#include <projectexplorer/projectexplorer.h>
|
||||
|
||||
@@ -51,6 +51,7 @@
|
||||
#include <QFileDialog>
|
||||
|
||||
using namespace ProjectExplorer;
|
||||
using namespace Utils;
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
@@ -224,7 +225,7 @@ void UnstartedAppWatcherDialog::startWatching()
|
||||
}
|
||||
}
|
||||
|
||||
void UnstartedAppWatcherDialog::pidFound(const DeviceProcessItem &p)
|
||||
void UnstartedAppWatcherDialog::pidFound(const ProcessInfo &p)
|
||||
{
|
||||
setWaitingState(FoundState);
|
||||
startStopTimer(false);
|
||||
@@ -256,16 +257,17 @@ void UnstartedAppWatcherDialog::startStopTimer(bool start)
|
||||
void UnstartedAppWatcherDialog::findProcess()
|
||||
{
|
||||
const QString &appName = m_pathChooser->filePath().normalizedPathName().toString();
|
||||
DeviceProcessItem fallback;
|
||||
foreach (const DeviceProcessItem &p, DeviceProcessList::localProcesses()) {
|
||||
if (Utils::FileUtils::normalizedPathName(p.exe) == appName) {
|
||||
pidFound(p);
|
||||
ProcessInfo fallback;
|
||||
const QList<ProcessInfo> processInfoList = ProcessInfo::processInfoList();
|
||||
for (const ProcessInfo &processInfo : processInfoList) {
|
||||
if (Utils::FileUtils::normalizedPathName(processInfo.executable) == appName) {
|
||||
pidFound(processInfo);
|
||||
return;
|
||||
}
|
||||
if (p.cmdLine.startsWith(appName))
|
||||
fallback = p;
|
||||
if (processInfo.commandLine.startsWith(appName))
|
||||
fallback = processInfo;
|
||||
}
|
||||
if (fallback.pid != 0)
|
||||
if (fallback.processId != 0)
|
||||
pidFound(fallback);
|
||||
}
|
||||
|
||||
@@ -302,7 +304,7 @@ Kit *UnstartedAppWatcherDialog::currentKit() const
|
||||
return m_kitChooser->currentKit();
|
||||
}
|
||||
|
||||
DeviceProcessItem UnstartedAppWatcherDialog::currentProcess() const
|
||||
ProcessInfo UnstartedAppWatcherDialog::currentProcess() const
|
||||
{
|
||||
return m_process;
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
#include <QDialog>
|
||||
#include <QTimer>
|
||||
|
||||
#include <projectexplorer/devicesupport/deviceprocesslist.h>
|
||||
#include <utils/processinfo.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QLabel;
|
||||
@@ -53,7 +53,7 @@ public:
|
||||
explicit UnstartedAppWatcherDialog(QWidget *parent = nullptr);
|
||||
|
||||
ProjectExplorer::Kit *currentKit() const;
|
||||
ProjectExplorer::DeviceProcessItem currentProcess() const;
|
||||
Utils::ProcessInfo currentProcess() const;
|
||||
bool hideOnAttach() const;
|
||||
bool continueOnAttach() const;
|
||||
void startWatching();
|
||||
@@ -65,7 +65,7 @@ signals:
|
||||
|
||||
private:
|
||||
void selectExecutable();
|
||||
void pidFound(const ProjectExplorer::DeviceProcessItem &p);
|
||||
void pidFound(const Utils::ProcessInfo &p);
|
||||
void startStopWatching(bool start);
|
||||
void findProcess();
|
||||
void stopAndCheckExecutable();
|
||||
@@ -89,7 +89,7 @@ private:
|
||||
QCheckBox *m_hideOnAttachCheckBox;
|
||||
QCheckBox *m_continueOnAttachCheckBox;
|
||||
QPushButton *m_watchingPushButton;
|
||||
ProjectExplorer::DeviceProcessItem m_process;
|
||||
Utils::ProcessInfo m_process;
|
||||
QTimer m_timer;
|
||||
};
|
||||
|
||||
|
||||
@@ -25,12 +25,11 @@
|
||||
|
||||
#include "desktopprocesssignaloperation.h"
|
||||
|
||||
#include "localprocesslist.h"
|
||||
|
||||
#include <app/app_version.h>
|
||||
|
||||
#include <utils/winutils.h>
|
||||
#include <utils/fileutils.h>
|
||||
#include <utils/processinfo.h>
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QDir>
|
||||
@@ -46,6 +45,8 @@
|
||||
#include <signal.h>
|
||||
#endif // else Q_OS_WIN
|
||||
|
||||
using namespace Utils;
|
||||
|
||||
namespace ProjectExplorer {
|
||||
|
||||
void DesktopProcessSignalOperation::killProcess(qint64 pid)
|
||||
@@ -57,9 +58,10 @@ void DesktopProcessSignalOperation::killProcess(qint64 pid)
|
||||
void DesktopProcessSignalOperation::killProcess(const QString &filePath)
|
||||
{
|
||||
m_errorMessage.clear();
|
||||
foreach (const DeviceProcessItem &process, Internal::LocalProcessList::getLocalProcesses()) {
|
||||
if (process.cmdLine == filePath)
|
||||
killProcessSilently(process.pid);
|
||||
const QList<ProcessInfo> processInfoList = ProcessInfo::processInfoList();
|
||||
for (const ProcessInfo &processInfo : processInfoList) {
|
||||
if (processInfo.commandLine == filePath)
|
||||
killProcessSilently(processInfo.processId);
|
||||
}
|
||||
emit finished(m_errorMessage);
|
||||
}
|
||||
@@ -74,9 +76,10 @@ void DesktopProcessSignalOperation::interruptProcess(qint64 pid)
|
||||
void DesktopProcessSignalOperation::interruptProcess(const QString &filePath)
|
||||
{
|
||||
m_errorMessage.clear();
|
||||
foreach (const DeviceProcessItem &process, Internal::LocalProcessList::getLocalProcesses()) {
|
||||
if (process.cmdLine == filePath)
|
||||
interruptProcessSilently(process.pid);
|
||||
const QList<ProcessInfo> processInfoList = ProcessInfo::processInfoList();
|
||||
for (const ProcessInfo &processInfo : processInfoList) {
|
||||
if (processInfo.commandLine == filePath)
|
||||
interruptProcessSilently(processInfo.processId);
|
||||
}
|
||||
emit finished(m_errorMessage);
|
||||
}
|
||||
@@ -105,7 +108,7 @@ void DesktopProcessSignalOperation::killProcessSilently(qint64 pid)
|
||||
|PROCESS_DUP_HANDLE|PROCESS_TERMINATE|PROCESS_CREATE_THREAD|PROCESS_SUSPEND_RESUME;
|
||||
if (const HANDLE handle = OpenProcess(rights, FALSE, DWORD(pid))) {
|
||||
if (!TerminateProcess(handle, UINT(-1)))
|
||||
appendMsgCannotKill(pid, Utils::winErrorMessage(GetLastError()));
|
||||
appendMsgCannotKill(pid, winErrorMessage(GetLastError()));
|
||||
CloseHandle(handle);
|
||||
} else {
|
||||
appendMsgCannotKill(pid, tr("Cannot open process."));
|
||||
@@ -123,10 +126,10 @@ void DesktopProcessSignalOperation::interruptProcessSilently(qint64 pid)
|
||||
#ifdef Q_OS_WIN
|
||||
enum SpecialInterrupt { NoSpecialInterrupt, Win32Interrupt, Win64Interrupt };
|
||||
|
||||
bool is64BitSystem = Utils::is64BitWindowsSystem();
|
||||
bool is64BitSystem = is64BitWindowsSystem();
|
||||
SpecialInterrupt si = NoSpecialInterrupt;
|
||||
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
|
||||
32 bit application inside a 64 bit environment.
|
||||
@@ -164,18 +167,18 @@ GDB 32bit | Api | Api | N/A | Win32
|
||||
inferior = OpenProcess(rights, FALSE, pid);
|
||||
if (inferior == NULL) {
|
||||
appendMsgCannotInterrupt(pid, tr("Cannot open process: %1")
|
||||
+ Utils::winErrorMessage(GetLastError()));
|
||||
+ winErrorMessage(GetLastError()));
|
||||
break;
|
||||
}
|
||||
bool creatorIs64Bit = Utils::is64BitWindowsBinary(
|
||||
Utils::FilePath::fromUserInput(QCoreApplication::applicationFilePath()));
|
||||
bool creatorIs64Bit = is64BitWindowsBinary(
|
||||
FilePath::fromUserInput(QCoreApplication::applicationFilePath()));
|
||||
if (!is64BitSystem
|
||||
|| si == NoSpecialInterrupt
|
||||
|| (si == Win64Interrupt && creatorIs64Bit)
|
||||
|| (si == Win32Interrupt && !creatorIs64Bit)) {
|
||||
if (!DebugBreakProcess(inferior)) {
|
||||
appendMsgCannotInterrupt(pid, tr("DebugBreakProcess failed:")
|
||||
+ QLatin1Char(' ') + Utils::winErrorMessage(GetLastError()));
|
||||
+ QLatin1Char(' ') + winErrorMessage(GetLastError()));
|
||||
}
|
||||
} else if (si == Win32Interrupt || si == Win64Interrupt) {
|
||||
QString executable = QCoreApplication::applicationDirPath();
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
|
||||
#include <utils/fancylineedit.h>
|
||||
#include <utils/itemviews.h>
|
||||
#include <utils/processinfo.h>
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <QDialogButtonBox>
|
||||
@@ -99,7 +100,7 @@ public:
|
||||
void handleProcessListUpdated();
|
||||
void handleProcessKilled();
|
||||
void updateButtons();
|
||||
DeviceProcessItem selectedProcess() const;
|
||||
ProcessInfo selectedProcess() const;
|
||||
|
||||
QDialog *q;
|
||||
DeviceProcessList *processList;
|
||||
@@ -279,11 +280,11 @@ void DeviceProcessesDialogPrivate::updateButtons()
|
||||
errorText->setVisible(!errorText->document()->isEmpty());
|
||||
}
|
||||
|
||||
DeviceProcessItem DeviceProcessesDialogPrivate::selectedProcess() const
|
||||
ProcessInfo DeviceProcessesDialogPrivate::selectedProcess() const
|
||||
{
|
||||
const QModelIndexList indexes = procView->selectionModel()->selectedIndexes();
|
||||
if (indexes.empty() || !processList)
|
||||
return DeviceProcessItem();
|
||||
return ProcessInfo();
|
||||
return processList->at(proxyModel.mapToSource(indexes.first()).row());
|
||||
}
|
||||
|
||||
@@ -352,7 +353,7 @@ void DeviceProcessesDialog::showAllDevices()
|
||||
d->updateDevice();
|
||||
}
|
||||
|
||||
DeviceProcessItem DeviceProcessesDialog::currentProcess() const
|
||||
ProcessInfo DeviceProcessesDialog::currentProcess() const
|
||||
{
|
||||
return d->selectedProcess();
|
||||
}
|
||||
|
||||
@@ -33,9 +33,10 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace Utils { class ProcessInfo; }
|
||||
|
||||
namespace ProjectExplorer {
|
||||
|
||||
class DeviceProcessItem;
|
||||
class KitChooser;
|
||||
|
||||
namespace Internal { class DeviceProcessesDialogPrivate; }
|
||||
@@ -52,7 +53,7 @@ public:
|
||||
|
||||
void setDevice(const IDevice::ConstPtr &device);
|
||||
void showAllDevices();
|
||||
DeviceProcessItem currentProcess() const;
|
||||
Utils::ProcessInfo currentProcess() const;
|
||||
KitChooser *kitChooser() const;
|
||||
void logMessage(const QString &line);
|
||||
DeviceProcessesDialog(KitChooser *chooser, QWidget *parent);
|
||||
|
||||
@@ -24,11 +24,11 @@
|
||||
****************************************************************************/
|
||||
|
||||
#include "deviceprocesslist.h"
|
||||
#include "localprocesslist.h"
|
||||
|
||||
#include <utils/fileutils.h>
|
||||
#include <utils/processinfo.h>
|
||||
#include <utils/qtcassert.h>
|
||||
#include <utils/treemodel.h>
|
||||
#include <utils/fileutils.h>
|
||||
|
||||
using namespace Utils;
|
||||
|
||||
@@ -40,12 +40,12 @@ enum State { Inactive, Listing, Killing };
|
||||
class DeviceProcessTreeItem : public TreeItem
|
||||
{
|
||||
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;
|
||||
Qt::ItemFlags flags(int) const final { return fl; }
|
||||
|
||||
DeviceProcessItem process;
|
||||
ProcessInfo process;
|
||||
Qt::ItemFlags fl;
|
||||
};
|
||||
|
||||
@@ -88,14 +88,14 @@ void DeviceProcessList::update()
|
||||
doUpdate();
|
||||
}
|
||||
|
||||
void DeviceProcessList::reportProcessListUpdated(const QList<DeviceProcessItem> &processes)
|
||||
void DeviceProcessList::reportProcessListUpdated(const QList<ProcessInfo> &processes)
|
||||
{
|
||||
QTC_ASSERT(d->state == Listing, return);
|
||||
setFinished();
|
||||
d->model.clear();
|
||||
for (const DeviceProcessItem &process : processes) {
|
||||
for (const ProcessInfo &process : processes) {
|
||||
Qt::ItemFlags fl;
|
||||
if (process.pid != d->ownPid)
|
||||
if (process.processId != d->ownPid)
|
||||
fl = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
|
||||
d->model.rootItem()->appendChild(new DeviceProcessTreeItem(process, fl));
|
||||
}
|
||||
@@ -125,7 +125,7 @@ void DeviceProcessList::reportProcessKilled()
|
||||
emit processKilled();
|
||||
}
|
||||
|
||||
DeviceProcessItem DeviceProcessList::at(int row) const
|
||||
ProcessInfo DeviceProcessList::at(int row) const
|
||||
{
|
||||
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 (column == 0)
|
||||
return process.pid ? process.pid : QVariant();
|
||||
return process.processId ? process.processId : QVariant();
|
||||
else
|
||||
return process.cmdLine;
|
||||
return process.commandLine;
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
@@ -163,18 +163,4 @@ void DeviceProcessList::reportError(const QString &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
|
||||
|
||||
@@ -32,20 +32,12 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace Utils { class ProcessInfo; }
|
||||
|
||||
namespace ProjectExplorer {
|
||||
|
||||
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
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -58,11 +50,9 @@ public:
|
||||
void killProcess(int row);
|
||||
void setOwnPid(qint64 pid);
|
||||
|
||||
DeviceProcessItem at(int row) const;
|
||||
Utils::ProcessInfo at(int row) const;
|
||||
QAbstractItemModel *model() const;
|
||||
|
||||
static QList<DeviceProcessItem> localProcesses();
|
||||
|
||||
signals:
|
||||
void processListUpdated();
|
||||
void error(const QString &errorMsg);
|
||||
@@ -71,13 +61,13 @@ signals:
|
||||
protected:
|
||||
void reportError(const QString &message);
|
||||
void reportProcessKilled();
|
||||
void reportProcessListUpdated(const QList<DeviceProcessItem> &processes);
|
||||
void reportProcessListUpdated(const QList<Utils::ProcessInfo> &processes);
|
||||
|
||||
IDevice::ConstPtr device() const;
|
||||
|
||||
private:
|
||||
virtual void doUpdate() = 0;
|
||||
virtual void doKillProcess(const DeviceProcessItem &process) = 0;
|
||||
virtual void doKillProcess(const Utils::ProcessInfo &process) = 0;
|
||||
|
||||
void setFinished();
|
||||
|
||||
|
||||
@@ -25,204 +25,42 @@
|
||||
|
||||
#include "localprocesslist.h"
|
||||
|
||||
#include <utils/qtcprocess.h>
|
||||
#include <utils/processinfo.h>
|
||||
|
||||
#include <QLibrary>
|
||||
#include <QTimer>
|
||||
|
||||
#ifdef Q_OS_UNIX
|
||||
#include <QDir>
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#if defined(Q_OS_UNIX)
|
||||
#include <unistd.h>
|
||||
#elif defined(Q_OS_WIN)
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#include <windows.h>
|
||||
#include <utils/winutils.h>
|
||||
#include <tlhelp32.h>
|
||||
#include <psapi.h>
|
||||
#endif
|
||||
using namespace Utils;
|
||||
|
||||
namespace ProjectExplorer {
|
||||
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)
|
||||
: DeviceProcessList(device, parent)
|
||||
{
|
||||
#if defined(Q_OS_UNIX)
|
||||
setOwnPid(getpid());
|
||||
#elif defined(Q_OS_WIN)
|
||||
setOwnPid(GetCurrentProcessId());
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool isUnixProcessId(const QString &procname)
|
||||
{
|
||||
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)
|
||||
void LocalProcessList::doKillProcess(const ProcessInfo &processInfo)
|
||||
{
|
||||
DeviceProcessSignalOperation::Ptr signalOperation = device()->signalOperation();
|
||||
connect(signalOperation.data(), &DeviceProcessSignalOperation::finished,
|
||||
this, &LocalProcessList::reportDelayedKillStatus);
|
||||
signalOperation->killProcess(process.pid);
|
||||
signalOperation->killProcess(processInfo.processId);
|
||||
}
|
||||
|
||||
void LocalProcessList::handleUpdate()
|
||||
{
|
||||
reportProcessListUpdated(getLocalProcesses());
|
||||
reportProcessListUpdated(ProcessInfo::processInfoList());
|
||||
}
|
||||
|
||||
void LocalProcessList::doUpdate()
|
||||
|
||||
@@ -37,11 +37,9 @@ class LocalProcessList : public DeviceProcessList
|
||||
public:
|
||||
explicit LocalProcessList(const IDevice::ConstPtr &device, QObject *parent = nullptr);
|
||||
|
||||
static QList<DeviceProcessItem> getLocalProcesses();
|
||||
|
||||
private:
|
||||
void doUpdate() override;
|
||||
void doKillProcess(const DeviceProcessItem &process) override;
|
||||
void doKillProcess(const Utils::ProcessInfo &process) override;
|
||||
|
||||
private:
|
||||
void handleUpdate();
|
||||
|
||||
@@ -28,10 +28,12 @@
|
||||
#include "idevice.h"
|
||||
|
||||
#include <ssh/sshremoteprocessrunner.h>
|
||||
#include <utils/qtcassert.h>
|
||||
#include <utils/fileutils.h>
|
||||
#include <utils/processinfo.h>
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
using namespace QSsh;
|
||||
using namespace Utils;
|
||||
|
||||
namespace ProjectExplorer {
|
||||
|
||||
@@ -58,13 +60,13 @@ void SshDeviceProcessList::doUpdate()
|
||||
d->process.run(listProcessesCommandLine(), device()->sshParameters());
|
||||
}
|
||||
|
||||
void SshDeviceProcessList::doKillProcess(const DeviceProcessItem &process)
|
||||
void SshDeviceProcessList::doKillProcess(const ProcessInfo &process)
|
||||
{
|
||||
d->signalOperation = device()->signalOperation();
|
||||
QTC_ASSERT(d->signalOperation, return);
|
||||
connect(d->signalOperation.data(), &DeviceProcessSignalOperation::finished,
|
||||
this, &SshDeviceProcessList::handleKillProcessFinished);
|
||||
d->signalOperation->killProcess(process.pid);
|
||||
d->signalOperation->killProcess(process.processId);
|
||||
}
|
||||
|
||||
void SshDeviceProcessList::handleConnectionError()
|
||||
|
||||
@@ -44,10 +44,10 @@ private:
|
||||
void handleKillProcessFinished(const QString &errorString);
|
||||
|
||||
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 doKillProcess(const DeviceProcessItem &process) override;
|
||||
void doKillProcess(const Utils::ProcessInfo &process) override;
|
||||
|
||||
void handleProcessError(const QString &errorMessage);
|
||||
void setFinished();
|
||||
|
||||
@@ -38,7 +38,6 @@
|
||||
#include <debugger/debuggerruncontrol.h>
|
||||
|
||||
#include <projectexplorer/devicesupport/deviceprocessesdialog.h>
|
||||
#include <projectexplorer/devicesupport/deviceprocesslist.h>
|
||||
#include <projectexplorer/devicesupport/deviceusedportsgatherer.h>
|
||||
#include <projectexplorer/kit.h>
|
||||
#include <projectexplorer/kitchooser.h>
|
||||
@@ -55,6 +54,7 @@
|
||||
|
||||
#include <utils/pathchooser.h>
|
||||
#include <utils/portlist.h>
|
||||
#include <utils/processinfo.h>
|
||||
#include <utils/qtcassert.h>
|
||||
#include <utils/qtcprocess.h>
|
||||
|
||||
@@ -244,8 +244,7 @@ void QnxAttachDebugSupport::showProcessesDialog()
|
||||
if (!runConfig)
|
||||
return;
|
||||
|
||||
DeviceProcessItem process = dlg.currentProcess();
|
||||
const int pid = process.pid;
|
||||
const int pid = dlg.currentProcess().processId;
|
||||
// QString projectSourceDirectory = dlg.projectSource();
|
||||
FilePath localExecutable = dlg.localExecutable();
|
||||
if (localExecutable.isEmpty()) {
|
||||
|
||||
@@ -27,12 +27,14 @@
|
||||
|
||||
#include <utils/algorithm.h>
|
||||
#include <utils/fileutils.h>
|
||||
#include <utils/processinfo.h>
|
||||
|
||||
#include <QRegularExpression>
|
||||
#include <QStringList>
|
||||
|
||||
using namespace Qnx;
|
||||
using namespace Qnx::Internal;
|
||||
using namespace Utils;
|
||||
|
||||
QnxDeviceProcessList::QnxDeviceProcessList(
|
||||
const ProjectExplorer::IDevice::ConstPtr &device, QObject *parent)
|
||||
@@ -45,10 +47,9 @@ QString QnxDeviceProcessList::listProcessesCommandLine() const
|
||||
return QLatin1String("pidin -F '%a %A {/%n}'");
|
||||
}
|
||||
|
||||
QList<ProjectExplorer::DeviceProcessItem> QnxDeviceProcessList::buildProcessList(
|
||||
const QString &listProcessesReply) const
|
||||
QList<ProcessInfo> QnxDeviceProcessList::buildProcessList(const QString &listProcessesReply) const
|
||||
{
|
||||
QList<ProjectExplorer::DeviceProcessItem> processes;
|
||||
QList<ProcessInfo> processes;
|
||||
QStringList lines = listProcessesReply.split(QLatin1Char('\n'));
|
||||
if (lines.isEmpty())
|
||||
return processes;
|
||||
@@ -64,10 +65,10 @@ QList<ProjectExplorer::DeviceProcessItem> QnxDeviceProcessList::buildProcessList
|
||||
const int pid = captures[1].toInt();
|
||||
const QString args = captures[2];
|
||||
const QString exe = captures[3];
|
||||
ProjectExplorer::DeviceProcessItem deviceProcess;
|
||||
deviceProcess.pid = pid;
|
||||
deviceProcess.exe = exe.trimmed();
|
||||
deviceProcess.cmdLine = args.trimmed();
|
||||
ProcessInfo deviceProcess;
|
||||
deviceProcess.processId = pid;
|
||||
deviceProcess.executable = exe.trimmed();
|
||||
deviceProcess.commandLine = args.trimmed();
|
||||
processes.append(deviceProcess);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,8 +40,7 @@ public:
|
||||
|
||||
private:
|
||||
QString listProcessesCommandLine() const override;
|
||||
QList<ProjectExplorer::DeviceProcessItem> buildProcessList(
|
||||
const QString &listProcessesReply) const override;
|
||||
QList<Utils::ProcessInfo> buildProcessList(const QString &listProcessesReply) const override;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
#include <utils/environment.h>
|
||||
#include <utils/hostosinfo.h>
|
||||
#include <utils/port.h>
|
||||
#include <utils/processinfo.h>
|
||||
#include <utils/qtcassert.h>
|
||||
#include <utils/stringutils.h>
|
||||
#include <utils/temporaryfile.h>
|
||||
@@ -100,12 +101,12 @@ private:
|
||||
"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)
|
||||
+ QString::fromLatin1(Delimiter1), Qt::SkipEmptyParts);
|
||||
foreach (const QString &line, lines) {
|
||||
for (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,
|
||||
@@ -132,10 +133,10 @@ private:
|
||||
+ QLatin1Char(']');
|
||||
}
|
||||
|
||||
DeviceProcessItem process;
|
||||
process.pid = pid;
|
||||
process.cmdLine = command;
|
||||
process.exe = elements.at(3);
|
||||
ProcessInfo process;
|
||||
process.processId = pid;
|
||||
process.commandLine = command;
|
||||
process.executable = elements.at(3);
|
||||
processes.append(process);
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,6 @@
|
||||
|
||||
#include <projectexplorer/devicesupport/desktopprocesssignaloperation.h>
|
||||
#include <projectexplorer/devicesupport/devicemanager.h>
|
||||
#include <projectexplorer/devicesupport/deviceprocesslist.h>
|
||||
#include <projectexplorer/projectexplorerconstants.h>
|
||||
|
||||
#include <qtsupport/qtversionmanager.h>
|
||||
|
||||
Reference in New Issue
Block a user