From 091a0a441da32e640b7cfa09fb42ef32752672bc Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 7 Aug 2012 14:54:06 +0200 Subject: [PATCH] debugger: cleanup hostProcessList This is now using the lists in the device implementation. Change-Id: I112faf25d20a94315ec3b432d39ae6cf66762225 Reviewed-by: Thomas Hartmann --- src/plugins/debugger/shared/hostutils.cpp | 148 -------------- src/plugins/debugger/shared/hostutils.h | 11 - .../devicesupport/localprocesslist.cpp | 189 +++++++++++++----- .../devicesupport/localprocesslist.h | 21 +- 4 files changed, 154 insertions(+), 215 deletions(-) diff --git a/src/plugins/debugger/shared/hostutils.cpp b/src/plugins/debugger/shared/hostutils.cpp index 1531ebada82..e9fdcd7d80f 100644 --- a/src/plugins/debugger/shared/hostutils.cpp +++ b/src/plugins/debugger/shared/hostutils.cpp @@ -56,61 +56,6 @@ namespace Internal { #ifdef Q_OS_WIN -// Resolve QueryFullProcessImageNameW out of kernel32.dll due -// to incomplete MinGW import libs and it not being present -// on Windows XP. -static BOOL queryFullProcessImageName(HANDLE h, DWORD flags, LPWSTR buffer, DWORD *size) -{ - // Resolve required symbols from the kernel32.dll - typedef BOOL (WINAPI *QueryFullProcessImageNameWProtoType) - (HANDLE, DWORD, LPWSTR, PDWORD); - static QueryFullProcessImageNameWProtoType queryFullProcessImageNameW = 0; - if (!queryFullProcessImageNameW) { - QLibrary kernel32Lib(QLatin1String("kernel32.dll"), 0); - if (kernel32Lib.isLoaded() || kernel32Lib.load()) - queryFullProcessImageNameW = (QueryFullProcessImageNameWProtoType)kernel32Lib.resolve("QueryFullProcessImageNameW"); - } - if (!queryFullProcessImageNameW) - return FALSE; - // Read out process - return (*queryFullProcessImageNameW)(h, flags, buffer, size); -} - -static QString imageName(DWORD processId) -{ - QString rc; - HANDLE handle = OpenProcess(PROCESS_QUERY_INFORMATION , FALSE, processId); - if (handle == INVALID_HANDLE_VALUE) - return rc; - WCHAR buffer[MAX_PATH]; - DWORD bufSize = MAX_PATH; - if (queryFullProcessImageName(handle, 0, buffer, &bufSize)) - rc = QString::fromUtf16(reinterpret_cast(buffer)); - CloseHandle(handle); - return rc; -} - -static QList winProcessList() -{ - QList rc; - - PROCESSENTRY32 pe; - pe.dwSize = sizeof(PROCESSENTRY32); - HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); - if (snapshot == INVALID_HANDLE_VALUE) - return rc; - - for (bool hasNext = Process32First(snapshot, &pe); hasNext; hasNext = Process32Next(snapshot, &pe)) { - ProcData procData; - procData.ppid = QString::number(pe.th32ProcessID); - procData.name = QString::fromUtf16(reinterpret_cast(pe.szExeFile)); - procData.image = imageName(pe.th32ProcessID); - rc.push_back(procData); - } - CloseHandle(snapshot); - return rc; -} - bool winResumeThread(unsigned long dwThreadId, QString *errorMessage) { bool ok = false; @@ -284,99 +229,6 @@ bool isFatalWinException(long code) return true; } -QList hostProcessList() -{ - return winProcessList(); -} - -#else // Q_OS_WIN - -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 running ps -static QList unixProcessListPS() -{ -#ifdef Q_OS_MAC - static const char formatC[] = "pid state command"; -#else - static const char formatC[] = "pid,state,cmd"; -#endif - QList rc; - QProcess psProcess; - QStringList args; - args << QLatin1String("-e") << QLatin1String("-o") << QLatin1String(formatC); - psProcess.start(QLatin1String("ps"), args); - if (!psProcess.waitForStarted()) - return rc; - QByteArray output; - if (!Utils::SynchronousProcess::readDataFromProcess(psProcess, 30000, &output, 0, false)) - return rc; - // Split "457 S+ /Users/foo.app" - 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).simplified(); - const int pidSep = line.indexOf(blank); - const int cmdSep = pidSep != -1 ? line.indexOf(blank, pidSep + 1) : -1; - if (cmdSep > 0) { - ProcData procData; - procData.ppid = line.left(pidSep); - procData.state = line.mid(pidSep + 1, cmdSep - pidSep - 1); - procData.name = line.mid(cmdSep + 1); - rc.push_back(procData); - } - } - return rc; -} - -// Determine UNIX processes by reading "/proc". Default to ps if -// it does not exist -static QList unixProcessList() -{ - const QDir procDir(QLatin1String("/proc/")); - if (!procDir.exists()) - return unixProcessListPS(); - QList rc; - const QStringList procIds = procDir.entryList(); - if (procIds.isEmpty()) - return rc; - foreach (const QString &procId, procIds) { - if (!isUnixProcessId(procId)) - continue; - QString filename = QLatin1String("/proc/"); - filename += procId; - filename += QLatin1String("/stat"); - QFile file(filename); - if (!file.open(QIODevice::ReadOnly)) - continue; // process may have exited - - const QStringList data = QString::fromLocal8Bit(file.readAll()).split(QLatin1Char(' ')); - ProcData proc; - proc.ppid = procId; - proc.name = data.at(1); - if (proc.name.startsWith(QLatin1Char('(')) && proc.name.endsWith(QLatin1Char(')'))) { - proc.name.truncate(proc.name.size() - 1); - proc.name.remove(0, 1); - } - proc.state = data.at(2); - // PPID is element 3 - rc.push_back(proc); - } - return rc; -} - -QList hostProcessList() -{ - return unixProcessList(); -} - #endif // Q_OS_WIN } // namespace Internal diff --git a/src/plugins/debugger/shared/hostutils.h b/src/plugins/debugger/shared/hostutils.h index a01e0ab7344..66d8e20f79c 100644 --- a/src/plugins/debugger/shared/hostutils.h +++ b/src/plugins/debugger/shared/hostutils.h @@ -41,17 +41,6 @@ QT_END_NAMESPACE namespace Debugger { namespace Internal { -struct ProcData -{ - QString ppid; - QString name; - QString image; - QString state; -}; - - -QList hostProcessList(); - #ifdef Q_OS_WIN // Resume a suspended thread by id. diff --git a/src/plugins/projectexplorer/devicesupport/localprocesslist.cpp b/src/plugins/projectexplorer/devicesupport/localprocesslist.cpp index 8b757c1c617..2c1f743af67 100644 --- a/src/plugins/projectexplorer/devicesupport/localprocesslist.cpp +++ b/src/plugins/projectexplorer/devicesupport/localprocesslist.cpp @@ -30,31 +30,27 @@ #include "localprocesslist.h" #include -#include #include +#ifdef Q_OS_UNIX +#include +#include +#include #include #include - -#ifdef Q_OS_UNIX -//#include -#include #endif #ifdef Q_OS_WIN - // Enable Win API of XP SP1 and later #define _WIN32_WINNT 0x0502 #include #include #include #include - -#endif // Q_OS_WIN +#endif namespace ProjectExplorer { namespace Internal { -const int PsFieldWidth = 50; #ifdef Q_OS_WIN @@ -91,29 +87,151 @@ static QString imageName(DWORD processId) CloseHandle(handle); return rc; } -#endif //Q_OS_WIN LocalProcessList::LocalProcessList(const IDevice::ConstPtr &device, QObject *parent) - : DeviceProcessList(device, parent), - m_psProcess(new QProcess(this)) + : DeviceProcessList(device, parent) { -#ifdef Q_OS_UNIX - connect(m_psProcess, SIGNAL(error(QProcess::ProcessError)), SLOT(handlePsError())); - connect(m_psProcess, SIGNAL(finished(int)), SLOT(handlePsFinished())); -#endif //Q_OS_UNIX +} + +void LocalProcessList::handleWindowsUpdate() +{ + QList processes; + + PROCESSENTRY32 pe; + pe.dwSize = sizeof(PROCESSENTRY32); + HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + if (snapshot == INVALID_HANDLE_VALUE) + return; + + for (bool hasNext = Process32First(snapshot, &pe); hasNext; hasNext = Process32Next(snapshot, &pe)) { + DeviceProcess p; + p.pid = pe.th32ProcessID; + p.exe = QString::fromUtf16(reinterpret_cast(pe.szExeFile)); + p.cmdLine = imageName(pe.th32ProcessID); + if (p.cmdLine.isEmpty()) + p.cmdLine = p.exe; + processes << p; + } + CloseHandle(snapshot); + + reportProcessListUpdated(processes); } void LocalProcessList::doUpdate() { + QTimer::singleShot(0, this, SLOT(handleWindowsUpdate())); +} + +void LocalProcessList::doKillProcess(const DeviceProcess &process) +{ + Q_UNUSED(process); +} + +#endif //Q_OS_WIN + + #ifdef Q_OS_UNIX +LocalProcessList::LocalProcessList(const IDevice::ConstPtr &device, QObject *parent) + : DeviceProcessList(device, parent), + m_psProcess(new QProcess(this)) +{ + connect(m_psProcess, SIGNAL(error(QProcess::ProcessError)), SLOT(handlePsError())); + connect(m_psProcess, SIGNAL(finished(int)), SLOT(handlePsFinished())); +} + +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 +void LocalProcessList::updateUsingProc() +{ + QList processes; + const QDir procDir(QLatin1String("/proc/")); + const QStringList procIds = procDir.entryList(); + foreach (const QString &procId, procIds) { + if (!isUnixProcessId(procId)) + continue; + QString filename = QLatin1String("/proc/"); + filename += procId; + filename += QLatin1String("/stat"); + QFile file(filename); + if (!file.open(QIODevice::ReadOnly)) + continue; // process may have exited + + const QStringList data = QString::fromLocal8Bit(file.readAll()).split(QLatin1Char(' ')); + DeviceProcess proc; + proc.pid = procId.toInt(); + proc.exe = data.at(1); + if (proc.exe.startsWith(QLatin1Char('(')) && proc.exe.endsWith(QLatin1Char(')'))) { + proc.exe.truncate(proc.exe.size() - 1); + proc.exe.remove(0, 1); + } + // PPID is element 3 + processes.push_back(proc); + } + reportProcessListUpdated(processes); +} + +//// Determine UNIX processes by running ps +//void updateUsingPs() +//{ +//#ifdef Q_OS_MAC +// static const char formatC[] = "pid state command"; +//#else +// static const char formatC[] = "pid,state,cmd"; +//#endif +// QList processes; +// QProcess psProcess; +// QStringList args; +// args << QLatin1String("-e") << QLatin1String("-o") << QLatin1String(formatC); +// psProcess.start(QLatin1String("ps"), args); +// if (psProcess.waitForStarted()) { +// QByteArray output; +// if (!Utils::SynchronousProcess::readDataFromProcess(psProcess, 30000, &output, 0, false)) +// return rc; +// // Split "457 S+ /Users/foo.app" +// 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).simplified(); +// const int pidSep = line.indexOf(blank); +// const int cmdSep = pidSep != -1 ? line.indexOf(blank, pidSep + 1) : -1; +// if (cmdSep > 0) { +// DeviceProcess procData; +// procData.pid = line.left(pidSep); +// procData.exe = line.mid(cmdSep + 1); +// procData.cmdLine = line.mid(cmdSep + 1); +// processes.push_back(procData); +// } +// } +// } +// reportProcessListUpdated(processes); +//} + +void LocalProcessList::doUpdate() +{ + const QDir procDir(QLatin1String("/proc/")); + if (procDir.exists()) + QTimer::singleShot(0, this, SLOT(updateUsingProc())); + else + updateUsingPs(); +} + +const int PsFieldWidth = 50; + +void LocalProcessList::updateUsingPs() +{ // We assume Desktop Unix systems to have a POSIX-compliant ps. // We need the padding because the command field can contain spaces, so we cannot split on those. m_psProcess->start(QString::fromLocal8Bit("ps -e -o pid=%1 -o comm=%1 -o args=%1") .arg(QString(PsFieldWidth, QChar('x')))); -#endif -#ifdef Q_OS_WIN - QTimer::singleShot(0, this, SLOT(handleWindowsUpdate())); -#endif } void LocalProcessList::handlePsFinished() @@ -151,32 +269,6 @@ void LocalProcessList::handlePsFinished() reportError(errorString); } -void LocalProcessList::handleWindowsUpdate() -{ -#ifdef Q_OS_WIN - QList processes; - - PROCESSENTRY32 pe; - pe.dwSize = sizeof(PROCESSENTRY32); - HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); - if (snapshot == INVALID_HANDLE_VALUE) - return; - - for (bool hasNext = Process32First(snapshot, &pe); hasNext; hasNext = Process32Next(snapshot, &pe)) { - DeviceProcess p; - p.pid = pe.th32ProcessID; - p.exe = QString::fromUtf16(reinterpret_cast(pe.szExeFile)); - p.cmdLine = imageName(pe.th32ProcessID); - if (p.cmdLine.isEmpty()) - p.cmdLine = p.exe; - processes << p; - } - CloseHandle(snapshot); - - reportProcessListUpdated(processes); -#endif -} - void LocalProcessList::handlePsError() { // Other errors are handled in the finished() handler. @@ -186,15 +278,11 @@ void LocalProcessList::handlePsError() void LocalProcessList::doKillProcess(const DeviceProcess &process) { -#ifdef Q_OS_UNIX if (kill(process.pid, SIGKILL) == -1) m_error = QString::fromLocal8Bit(strerror(errno)); else m_error.clear(); QTimer::singleShot(0, this, SLOT(reportDelayedKillStatus())); -#else - Q_UNUSED(process); -#endif } void LocalProcessList::reportDelayedKillStatus() @@ -204,6 +292,7 @@ void LocalProcessList::reportDelayedKillStatus() else reportError(m_error); } +#endif // QT_OS_UNIX } // namespace Internal } // namespace RemoteLinux diff --git a/src/plugins/projectexplorer/devicesupport/localprocesslist.h b/src/plugins/projectexplorer/devicesupport/localprocesslist.h index c49412ce526..e099d3ebc66 100644 --- a/src/plugins/projectexplorer/devicesupport/localprocesslist.h +++ b/src/plugins/projectexplorer/devicesupport/localprocesslist.h @@ -48,18 +48,27 @@ class LocalProcessList : public DeviceProcessList public: LocalProcessList(const IDevice::ConstPtr &device, QObject *parent = 0); -private slots: - void handlePsError(); - void handlePsFinished(); - void handleWindowsUpdate(); - void reportDelayedKillStatus(); - private: void doUpdate(); void doKillProcess(const DeviceProcess &process); +#ifdef Q_OS_WIN +private slots: + void handleWindowsUpdate(); +#endif + +#ifdef Q_OS_UNIX +private slots: + void handlePsError(); + void handlePsFinished(); + void reportDelayedKillStatus(); + void updateUsingProc(); + void updateUsingPs(); + +private: QProcess * const m_psProcess; QString m_error; +#endif }; } // namespace Internal