[gimp] Bug 678925 - Debugging plugins with windows



commit 37d4f656d49051410c99156d86c8a4cb8ccafa12
Author: Michael Natterer <mitch gimp org>
Date:   Sat Feb 23 16:25:58 2013 +0100

    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.

 devel-docs/debug-plug-ins.txt |    9 +++-
 libgimp/gimp.c                |   43 ++++++++++++++++-
 tools/Makefile.am             |   12 +++++
 tools/gimp-debug-resume.c     |  110 +++++++++++++++++++++++++++++++++++++++++
 4 files changed, 172 insertions(+), 2 deletions(-)
---
diff --git a/devel-docs/debug-plug-ins.txt b/devel-docs/debug-plug-ins.txt
index f1c874b..3e8befa 100644
--- a/devel-docs/debug-plug-ins.txt
+++ b/devel-docs/debug-plug-ins.txt
@@ -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.
diff --git a/libgimp/gimp.c b/libgimp/gimp.c
index 0f6e386..5205780 100644
--- a/libgimp/gimp.c
+++ b/libgimp/gimp.c
@@ -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
 }
 
diff --git a/tools/Makefile.am b/tools/Makefile.am
index e78621e..b2e595e 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -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 = \
diff --git a/tools/gimp-debug-resume.c b/tools/gimp-debug-resume.c
new file mode 100644
index 0000000..57633bf
--- /dev/null
+++ b/tools/gimp-debug-resume.c
@@ -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;
+}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]