diff options
Diffstat (limited to 'src/plugins/debugger/procinterrupt.cpp')
-rw-r--r-- | src/plugins/debugger/procinterrupt.cpp | 182 |
1 files changed, 182 insertions, 0 deletions
diff --git a/src/plugins/debugger/procinterrupt.cpp b/src/plugins/debugger/procinterrupt.cpp new file mode 100644 index 0000000000..29d4d5803d --- /dev/null +++ b/src/plugins/debugger/procinterrupt.cpp @@ -0,0 +1,182 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Qt Software Information (qt-info@nokia.com) +** +** +** Non-Open Source Usage +** +** Licensees may use this file in accordance with the Qt Beta Version +** License Agreement, Agreement version 2.2 provided with the Software or, +** alternatively, in accordance with the terms contained in a written +** agreement between you and Nokia. +** +** GNU General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the packaging +** of this file. Please review the following information to ensure GNU +** General Public Licensing requirements will be met: +** +** http://www.fsf.org/licensing/licenses/info/GPLv2.html and +** http://www.gnu.org/copyleft/gpl.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt GPL Exception version +** 1.2, included in the file GPL_EXCEPTION.txt in this package. +** +***************************************************************************/ +#include "procinterrupt.h" + +#ifdef Q_OS_WIN +#include <windows.h> +#include <Tlhelp32.h> + +using namespace Debugger::Internal; + +typedef HANDLE (WINAPI *PtrCreateRemoteThread)( + HANDLE hProcess, + LPSECURITY_ATTRIBUTES lpThreadAttributes, + SIZE_T dwStackSize, + LPTHREAD_START_ROUTINE lpStartAddress, + LPVOID lpParameter, + DWORD dwCreationFlags, + LPDWORD lpThreadId); + +PtrCreateRemoteThread resolveCreateRemoteThread() +{ + HINSTANCE hLib = LoadLibraryA("Kernel32"); + return (PtrCreateRemoteThread)GetProcAddress(hLib, "CreateRemoteThread"); +} + +DWORD findProcessId(DWORD parentId) +{ + HANDLE hProcList = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + + PROCESSENTRY32 procEntry; + procEntry.dwSize = sizeof(PROCESSENTRY32); + + DWORD procId = 0; + + BOOL moreProc = Process32First(hProcList, &procEntry); + while (moreProc) { + if (procEntry.th32ParentProcessID == parentId) { + procId = procEntry.th32ProcessID; + break; + } + moreProc = Process32Next(hProcList, &procEntry); + } + + CloseHandle(hProcList); + return procId; +} +#else + +#include <QtCore/QLatin1String> +#include <QtCore/QString> +#include <QtCore/QDir> +#include <QtCore/QFileInfoList> +#include <QtCore/QByteArray> +#include <QtCore/QDebug> + +#include <sys/types.h> +#include <signal.h> + +#include <sys/sysctl.h> + +#define OPProcessValueUnknown UINT_MAX + +/* Mac OS X +int OPParentIDForProcessID(int pid) + // Returns the parent process id for the given process id (pid) +{ + struct kinfo_proc info; + size_t length = sizeof(struct kinfo_proc); + int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, pid }; + if (sysctl(mib, 4, &info, &length, NULL, 0) < 0) + return OPProcessValueUnknown; + if (length == 0) + return OPProcessValueUnknown; + return info.kp_eproc.e_ppid; +} +*/ + +int findParentProcess(int procId) +{ + QFile statFile(QLatin1String("/proc/") + QString::number(procId) + + QLatin1String("/stat")); + if (!statFile.open(QIODevice::ReadOnly)) + return -1; + + QByteArray line = statFile.readLine(); + line = line.mid(line.indexOf(')') + 4); + //qDebug() << "1: " << line; + line = line.left(line.indexOf(' ')); + //qDebug() << "2: " << line; + + return QString(line).toInt(); +} + +int findChildProcess(int parentId) +{ + QDir proc(QLatin1String("/proc")); + QFileInfoList procList = proc.entryInfoList(QDir::Dirs); + foreach (const QFileInfo &info, procList) { + int procId = 0; + bool ok = false; + procId = info.baseName().toInt(&ok); + if (!ok || !procId) + continue; + + if (findParentProcess(procId) == parentId) + return procId; + } + + return -1; +} + +#endif + +bool Debugger::Internal::interruptProcess(int pID) +{ +#ifdef Q_OS_WIN + DWORD pid = pID; + if (!pid) + return false; + + PtrCreateRemoteThread libFunc = resolveCreateRemoteThread(); + if (libFunc) { + DWORD dwThreadId = 0; + HANDLE hproc = OpenProcess(PROCESS_ALL_ACCESS, false, pid); + HANDLE hthread = libFunc(hproc, NULL, 0, (LPTHREAD_START_ROUTINE)DebugBreak, 0, 0, &dwThreadId); + CloseHandle(hthread); + if (dwThreadId) + return true; + } +#else + int procId = pID; + if (procId != -1) { + if (kill(procId, 2) == 0) + return true; + } + +#endif + + return false; +} + +bool Debugger::Internal::interruptChildProcess(Q_PID parentPID) +{ +#ifdef WIN32 + DWORD pid = findProcessId(parentPID->dwProcessId); + return interruptProcess(pid); +#else + int procId = findChildProcess(parentPID); + //qDebug() << "INTERRUPTING PROCESS" << procId; + return interruptProcess(procId); +#endif +} |