mirror of https://github.com/GNOME/gimp.git
Bug 678925 - Debugging plugins with windows
Apply patch from Hartmut Kuhse that enables plug-in debugging on Windows by stopping the process using Windows API, and providing a small executable "gimp-plugin-resume.exe" to resume the stopped plug-in.
This commit is contained in:
parent
e4f24a539e
commit
37d4f656d4
|
@ -46,7 +46,9 @@ The steps to debug a plug-in are as follows:
|
|||
5. Set breakpoints where you want the plug-in to stop in the debugger
|
||||
|
||||
6. Send the CONT signal (kill -CONT <pid>) to the plug-in process
|
||||
|
||||
(When compiled with Windows, resume the plug-in process with
|
||||
gimp-debug-resume.exe <pid>)
|
||||
|
||||
7. Enter "continue" in the debugger. The plug-in will then continue
|
||||
and break at the breakpoints.
|
||||
|
||||
|
@ -105,3 +107,8 @@ GIMP_PLUGIN_DEBUG_WRAPPER=debugger
|
|||
debugger refers to the debugger program, such as valgrind. You can
|
||||
put command line options here too, they will be parsed like they do
|
||||
in the shell.
|
||||
|
||||
When compiled with Windows, the plug-in process is halted by Windows functions.
|
||||
It must be resumed externally by invoking gimp-debug-resume.exe <pid>
|
||||
The plug-ins pid can be found out by invoking gimp-debug-resume.exe
|
||||
without parameters. It shows the pid of all running processes.
|
||||
|
|
|
@ -90,6 +90,7 @@
|
|||
# define STRICT
|
||||
# define _WIN32_WINNT 0x0601
|
||||
# include <windows.h>
|
||||
# include <tlhelp32.h>
|
||||
# undef RGB
|
||||
# define USE_WIN32_SHM 1
|
||||
#endif
|
||||
|
@ -1649,10 +1650,50 @@ static void
|
|||
gimp_debug_stop (void)
|
||||
{
|
||||
#ifndef G_OS_WIN32
|
||||
|
||||
g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Waiting for debugger...");
|
||||
raise (SIGSTOP);
|
||||
|
||||
#else
|
||||
g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Debugging not implemented on Win32");
|
||||
|
||||
HANDLE hThreadSnap = NULL;
|
||||
THREADENTRY32 te32 = { 0 };
|
||||
pid_t opid = getpid ();
|
||||
|
||||
g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Debugging (restart externally): %d",
|
||||
opid);
|
||||
|
||||
hThreadSnap = CreateToolhelp32Snapshot (TH32CS_SNAPTHREAD, 0);
|
||||
if (hThreadSnap == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG,
|
||||
"error getting threadsnap - debugging impossible");
|
||||
return;
|
||||
}
|
||||
|
||||
te32.dwSize = sizeof (THREADENTRY32);
|
||||
|
||||
if (Thread32First (hThreadSnap, &te32))
|
||||
{
|
||||
do
|
||||
{
|
||||
if (te32.th32OwnerProcessID == opid)
|
||||
{
|
||||
HANDLE hThread = OpenThread (THREAD_SUSPEND_RESUME, FALSE,
|
||||
te32.th32ThreadID);
|
||||
SuspendThread (hThread);
|
||||
CloseHandle (hThread);
|
||||
}
|
||||
}
|
||||
while (Thread32Next (hThreadSnap, &te32));
|
||||
}
|
||||
else
|
||||
{
|
||||
g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "error getting threads");
|
||||
}
|
||||
|
||||
CloseHandle (hThreadSnap);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -10,8 +10,20 @@ endif
|
|||
|
||||
SUBDIRS = $(D_pdbgen)
|
||||
|
||||
if OS_WIN32
|
||||
|
||||
bin_PROGRAMS = \
|
||||
gimptool-2.0 \
|
||||
gimp-debug-resume
|
||||
|
||||
gimp_debug_resume_SOURCES = gimp-debug-resume.c
|
||||
|
||||
else
|
||||
|
||||
bin_PROGRAMS = gimptool-2.0
|
||||
|
||||
endif
|
||||
|
||||
noinst_PROGRAMS = test-clipboard
|
||||
|
||||
EXTRA_PROGRAMS = \
|
||||
|
|
|
@ -0,0 +1,110 @@
|
|||
/* based on pausep by Daniel Turini
|
||||
*/
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define _WIN32_WINNT 0x0502
|
||||
#include <windows.h>
|
||||
#include <tchar.h>
|
||||
#include <tlhelp32.h>
|
||||
#include <stdio.h>
|
||||
|
||||
static BOOL
|
||||
resume_process (DWORD dwOwnerPID)
|
||||
{
|
||||
HANDLE hThreadSnap = NULL;
|
||||
BOOL bRet = FALSE;
|
||||
THREADENTRY32 te32 = { 0 };
|
||||
|
||||
hThreadSnap = CreateToolhelp32Snapshot (TH32CS_SNAPTHREAD, 0);
|
||||
if (hThreadSnap == INVALID_HANDLE_VALUE)
|
||||
return FALSE;
|
||||
|
||||
te32.dwSize = sizeof (THREADENTRY32);
|
||||
|
||||
if (Thread32First (hThreadSnap, &te32))
|
||||
{
|
||||
do
|
||||
{
|
||||
if (te32.th32OwnerProcessID == dwOwnerPID)
|
||||
{
|
||||
HANDLE hThread = OpenThread (THREAD_SUSPEND_RESUME, FALSE, te32.th32ThreadID);
|
||||
printf ("Resuming Thread: %u\n",te32.th32ThreadID);
|
||||
ResumeThread (hThread);
|
||||
CloseHandle (hThread);
|
||||
}
|
||||
}
|
||||
while (Thread32Next (hThreadSnap, &te32));
|
||||
bRet = TRUE;
|
||||
}
|
||||
else
|
||||
bRet = FALSE;
|
||||
|
||||
CloseHandle (hThreadSnap);
|
||||
|
||||
return bRet;
|
||||
}
|
||||
|
||||
static BOOL
|
||||
process_list (void)
|
||||
{
|
||||
HANDLE hProcessSnap = NULL;
|
||||
BOOL bRet = FALSE;
|
||||
PROCESSENTRY32 pe32 = {0};
|
||||
|
||||
hProcessSnap = CreateToolhelp32Snapshot (TH32CS_SNAPPROCESS, 0);
|
||||
|
||||
if (hProcessSnap == INVALID_HANDLE_VALUE)
|
||||
return FALSE;
|
||||
|
||||
pe32.dwSize = sizeof (PROCESSENTRY32);
|
||||
|
||||
if (Process32First (hProcessSnap, &pe32))
|
||||
{
|
||||
do
|
||||
{
|
||||
printf ("PID:\t%u\t%s\n", pe32.th32ProcessID, pe32.szExeFile);
|
||||
}
|
||||
while (Process32Next (hProcessSnap, &pe32));
|
||||
bRet = TRUE;
|
||||
}
|
||||
else
|
||||
bRet = FALSE;
|
||||
|
||||
CloseHandle (hProcessSnap);
|
||||
|
||||
return bRet;
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc,
|
||||
char* argv[])
|
||||
{
|
||||
DWORD pid;
|
||||
|
||||
if (argc <= 1)
|
||||
{
|
||||
process_list ();
|
||||
}
|
||||
else if (argc == 2)
|
||||
{
|
||||
pid = atoi (argv[1]);
|
||||
if (pid == 0)
|
||||
{
|
||||
printf ("invalid: %s\n", pid);
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf ("process: %u\n", pid);
|
||||
resume_process (pid);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf ("Usage:\n"
|
||||
"resume : show processlist\n"
|
||||
"resume PID: resuming thread\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue