[gimp] libgimp: add an exception handler for Windows.
- From: Jehan Pagès <jehanp src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] libgimp: add an exception handler for Windows.
- Date: Wed, 4 Apr 2018 18:31:10 +0000 (UTC)
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]