[gimp] libgimp: add an exception handler for Windows.



commit fa02a2c64f5fcaaceff34cea2bd02c5e558c63ca
Author: Jehan <jehan girinstud io>
Date:   Wed Apr 4 18:04:34 2018 +0200

    libgimp: add an exception handler for Windows.
    
    Drmingw already added its own exception handler which generates crash
    traces in a text file, for plug-ins as well. This additional handler is
    run after Drmingw handler and allows us to do things on our own, and in
    particular we could display the content of the debug traces.
    
    Right now it simply prints these to stderr, which actually won't be of
    much use on Win32, first because the console is deactivated on stable
    releases, also because after tests, it doesn't look like even running
    GIMP from cmd outputs to console either.
    
    We currently don't use the same debug dialog as the core on purpose,
    because we don't want everyone to send us traces for every unmaintained
    third party plug-ins out there. But we should definitely allow easier
    trace possibilities at some point, first to improve/debug our own core
    plug-ins, and also to help third party plug-in developers!
    So this commit is not making visible changes yet but is actually a first
    step towards these debugging goals.

 libgimp/gimp.c |   80 +++++++++++++++++++++++++++++++++++++++++++++++--------
 1 files changed, 68 insertions(+), 12 deletions(-)
---
diff --git a/libgimp/gimp.c b/libgimp/gimp.c
index f42087b..75ec23c 100644
--- a/libgimp/gimp.c
+++ b/libgimp/gimp.c
@@ -167,7 +167,11 @@ static void       gimp_fatal_func              (const gchar    *log_domain,
                                                 GLogLevelFlags  flags,
                                                 const gchar    *message,
                                                 gpointer        data);
-#ifndef G_OS_WIN32
+#ifdef G_OS_WIN32
+#ifdef HAVE_EXCHNDL
+static LONG WINAPI gimp_plugin_sigfatal_handler (PEXCEPTION_POINTERS pExceptionInfo);
+#endif
+#else
 static void       gimp_plugin_sigfatal_handler (gint            sig_num);
 #endif
 static gboolean   gimp_plugin_io_error_handler (GIOChannel      *channel,
@@ -193,8 +197,13 @@ static void       gimp_set_pdb_error           (const GimpParam *return_vals,
                                                 gint             n_return_vals);
 
 
-static GIOChannel *_readchannel  = NULL;
-GIOChannel *_writechannel = NULL;
+#if defined G_OS_WIN32 && defined HAVE_EXCHNDL
+static LPTOP_LEVEL_EXCEPTION_FILTER  _prevExceptionFilter    = NULL;
+static gchar                         *plug_in_backtrace_path = NULL;
+#endif
+
+static GIOChannel                   *_readchannel            = NULL;
+GIOChannel                          *_writechannel           = NULL;
 
 #ifdef USE_WIN32_SHM
 static HANDLE shm_handle;
@@ -332,10 +341,9 @@ gimp_main (const GimpPlugInInfo *info,
 #ifdef HAVE_EXCHNDL
   /* Use Dr. Mingw (dumps backtrace on crash) if it is available. */
   {
-    time_t t;
-    gchar *filename;
-    gchar *dir;
-    gchar *path;
+    time_t  t;
+    gchar  *filename;
+    gchar  *dir;
 
     /* This has to be the non-roaming directory (i.e., the local
        directory) as backtraces correspond to the binaries on this
@@ -349,14 +357,18 @@ gimp_main (const GimpPlugInInfo *info,
     time (&t);
     filename = g_strdup_printf ("%s-crash-%" G_GUINT64_FORMAT ".txt",
                                 g_get_prgname(), t);
-    path = g_build_filename (dir, filename, NULL);
+    plug_in_backtrace_path = g_build_filename (dir, filename, NULL);
     g_free (filename);
     g_free (dir);
 
-    ExcHndlInit ();
-    ExcHndlSetLogFileNameA (path);
+    /* Similar to core crash handling in app/signals.c, the order here
+     * is very important!
+     */
+    if (! _prevExceptionFilter)
+      _prevExceptionFilter = SetUnhandledExceptionFilter (gimp_plugin_sigfatal_handler);
 
-    g_free (path);
+    ExcHndlInit ();
+    ExcHndlSetLogFileNameA (plug_in_backtrace_path);
   }
 #endif
 
@@ -672,6 +684,11 @@ gimp_quit (void)
 {
   gimp_close ();
 
+#if defined G_OS_WIN32 && defined HAVE_EXCHNDL
+  if (plug_in_backtrace_path)
+    g_free (plug_in_backtrace_path);
+#endif
+
   exit (EXIT_SUCCESS);
 }
 
@@ -1986,7 +2003,46 @@ gimp_fatal_func (const gchar    *log_domain,
    */
 }
 
-#ifndef G_OS_WIN32
+#ifdef G_OS_WIN32
+
+#ifdef HAVE_EXCHNDL
+static LONG WINAPI
+gimp_plugin_sigfatal_handler (PEXCEPTION_POINTERS pExceptionInfo)
+{
+  g_printerr ("%s: fatal error\n", progname);
+
+  SetUnhandledExceptionFilter (_prevExceptionFilter);
+
+  /* For simplicity, do not make a difference between QUERY and ALWAYS
+   * on Windows (at least not for now).
+   */
+  if (stack_trace_mode != GIMP_STACK_TRACE_NEVER &&
+      g_file_test (plug_in_backtrace_path, G_FILE_TEST_IS_REGULAR))
+    {
+      FILE   *stream;
+      guchar  buffer[256];
+      size_t  read_len;
+
+      stream = fopen (plug_in_backtrace_path, "r");
+      do
+        {
+          /* Just read and output directly the file content. */
+          read_len = fread (buffer, 1, sizeof (buffer) - 1, stream);
+          buffer[read_len] = '\0';
+          g_printerr ("%s", buffer);
+        }
+      while (read_len);
+      fclose (stream);
+    }
+
+  if (_prevExceptionFilter && _prevExceptionFilter != gimp_plugin_sigfatal_handler)
+    return _prevExceptionFilter (pExceptionInfo);
+  else
+    return EXCEPTION_CONTINUE_SEARCH;
+}
+#endif
+
+#else
 static void
 gimp_plugin_sigfatal_handler (gint sig_num)
 {


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