[gimp] app, tools: use the new gimp_print_stack_trace() to output the...
- From: Jehan Pagès <jehanp src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] app, tools: use the new gimp_print_stack_trace() to output the...
- Date: Thu, 8 Feb 2018 15:37:47 +0000 (UTC)
commit 8d2ae895bd03269eedf147983c99cfd07eb79732
Author: Jehan <jehan girinstud io>
Date: Thu Feb 8 03:52:54 2018 +0100
app, tools: use the new gimp_print_stack_trace() to output the...
... stacktrace into a file on non-Win32 systems.
This has a few advantages:
- First, we don't need to duplicate stacktrace code inside the
independent gimp-debug-tool (I even noticed that the version in the
tool was gdb-only and not updated for lldb fallback; proof that code
duplication is evil!). Instead, even on a crash, we can create the
stacktrace from the main binary and simply pass it as a file.
- Secondly, that allows to fallback to the backtrace() API even for
crashes (this was not possible if the backtrace was done from a
completely different process). That's nice because this makes that we
will always get backtraces in Linux (even though backtrace() API is
not as nice as gdb/lldb, it's better than nothing).
- Finally this makes the code smaller (i.e. easier to maintain), more
consistent and similar on all platforms.
app/errors.c | 31 +++++++++++------------
app/signals.c | 37 ++++++++++++++--------------
tools/gimp-debug-tool.c | 61 ++++++----------------------------------------
3 files changed, 42 insertions(+), 87 deletions(-)
---
diff --git a/app/errors.c b/app/errors.c
index 416ec7b..9fc9fd0 100644
--- a/app/errors.c
+++ b/app/errors.c
@@ -34,6 +34,7 @@
#include <gio/gio.h>
#include <glib/gprintf.h>
+#include <glib/gstdio.h>
#include "libgimpbase/gimpbase.h"
@@ -300,6 +301,9 @@ gimp_eek (const gchar *reason,
#ifndef GIMP_CONSOLE_COMPILATION
if (generate_backtrace && ! the_errors_gimp->no_interface)
{
+ FILE *fd;
+ gboolean has_backtrace = TRUE;
+
/* If GUI backtrace enabled (it is disabled by default), it
* takes precedence over the command line argument.
*/
@@ -318,30 +322,26 @@ gimp_eek (const gchar *reason,
g_snprintf (pid, 16, "%u", (guint) getpid ());
args[2] = pid;
+#ifndef G_OS_WIN32
+ /* On Win32, the trace has already been processed by ExcHnl
+ * and is waiting for us in a text file.
+ */
+ fd = g_fopen (backtrace_file, "w");
+ has_backtrace = gimp_print_stack_trace (fd, NULL);
+ fclose (fd);
+#endif
+
/* We don't care about any return value. If it fails, too
* bad, we just won't have any stack trace.
* We still need to use the sync() variant because we have
* to keep GIMP up long enough for the debugger to get its
* trace.
*/
-#ifdef HAVE_EXCHNDL
- /* On Win32, the trace has already been processed by ExcHnl
- * and is waiting for us in a text file.
- * We just want to spawn the trace GUI and exit GIMP directly.
- */
- if (g_file_test (backtrace_file, G_FILE_TEST_IS_REGULAR) &&
+ if (has_backtrace &&
+ g_file_test (backtrace_file, G_FILE_TEST_IS_REGULAR) &&
g_spawn_async (NULL, args, NULL,
G_SPAWN_SEARCH_PATH | G_SPAWN_STDERR_TO_DEV_NULL | G_SPAWN_STDOUT_TO_DEV_NULL,
NULL, NULL, NULL, NULL))
-#else
- /* On Unix machines, the spawned process will attach to the
- * main GIMP process and will generate the backtrace. So we
- * run it as a synced process.
- */
- if (g_spawn_sync (NULL, args, NULL,
- G_SPAWN_SEARCH_PATH | G_SPAWN_STDERR_TO_DEV_NULL | G_SPAWN_STDOUT_TO_DEV_NULL,
- NULL, NULL, NULL, NULL, NULL, NULL))
-#endif
eek_handled = TRUE;
}
#endif /* !GIMP_CONSOLE_COMPILATION */
@@ -361,7 +361,6 @@ gimp_eek (const gchar *reason,
sigemptyset (&sigset);
sigprocmask (SIG_SETMASK, &sigset, NULL);
-
gimp_on_error_query ();
}
break;
diff --git a/app/signals.c b/app/signals.c
index 54ea9f6..08550ef 100644
--- a/app/signals.c
+++ b/app/signals.c
@@ -49,27 +49,10 @@ static void gimp_sigfatal_handler (gint sig_num) G_GNUC_NORETURN;
void
gimp_init_signal_handlers (gchar **backtrace_file)
{
-#ifdef G_OS_WIN32
- /* Use Dr. Mingw (dumps backtrace on crash) if it is available. Do
- * nothing otherwise on Win32.
- * The user won't get any stack trace from glib anyhow.
- * Without Dr. MinGW, It's better to let Windows inform about the
- * program error, and offer debugging (if the user has installed MSVC
- * or some other compiler that knows how to install itself as a
- * handler for program errors).
- */
-#ifdef HAVE_EXCHNDL
time_t t;
gchar *filename;
gchar *dir;
- /* Order is very important here. We need to add our signal handler
- * first, then run ExcHndlInit() which will add its own handler, so
- * that ExcHnl's handler runs first since that's in FILO order.
- */
- if (! g_prevExceptionFilter)
- g_prevExceptionFilter = SetUnhandledExceptionFilter (gimp_sigfatal_handler);
-
/* This has to be the non-roaming directory (i.e., the local
directory) as backtraces correspond to the binaries on this
system. */
@@ -81,11 +64,29 @@ gimp_init_signal_handlers (gchar **backtrace_file)
time (&t);
filename = g_strdup_printf ("%s-crash-%" G_GUINT64_FORMAT ".txt",
- g_get_prgname(), t);
+ g_get_prgname (), t);
*backtrace_file = g_build_filename (dir, filename, NULL);
g_free (filename);
g_free (dir);
+#ifdef G_OS_WIN32
+ /* Use Dr. Mingw (dumps backtrace on crash) if it is available. Do
+ * nothing otherwise on Win32.
+ * The user won't get any stack trace from glib anyhow.
+ * Without Dr. MinGW, It's better to let Windows inform about the
+ * program error, and offer debugging (if the user has installed MSVC
+ * or some other compiler that knows how to install itself as a
+ * handler for program errors).
+ */
+
+#ifdef HAVE_EXCHNDL
+ /* Order is very important here. We need to add our signal handler
+ * first, then run ExcHndlInit() which will add its own handler, so
+ * that ExcHnl's handler runs first since that's in FILO order.
+ */
+ if (! g_prevExceptionFilter)
+ g_prevExceptionFilter = SetUnhandledExceptionFilter (gimp_sigfatal_handler);
+
ExcHndlInit ();
ExcHndlSetLogFileNameA (*backtrace_file);
diff --git a/tools/gimp-debug-tool.c b/tools/gimp-debug-tool.c
index db4e096..e5bf2cd 100644
--- a/tools/gimp-debug-tool.c
+++ b/tools/gimp-debug-tool.c
@@ -16,16 +16,13 @@
*/
/*
- * GimpDebug simply runs a debugger on a given executable and PID and
- * displays a dialog proposing to create a bug report. The reason why it
+ * GimpDebug simply displays a dialog with debug data (backtraces,
+ * version, etc.), proposing to create a bug report. The reason why it
* is a separate executable is simply that when the program crashed,
* even though some actions are possible before exit() by catching fatal
- * errors and signals, it may not be possible anymore to allocate memory
- * anymore. Therefore creating a new dialog, or even just allocating a
- * string with the contents of the debugger are impossible actions.
+ * errors and signals, it may not be possible to allocate memory
+ * anymore. Therefore creating a new dialog is an impossible action.
* So we call instead a separate program, then exit.
- *
- * Note: this initial version does not handle Windows yet.
*/
#include <stdlib.h>
@@ -43,10 +40,6 @@
#include "app/widgets/gimpcriticaldialog.h"
-static gchar * gimp_debug_get_stack_trace (const gchar *full_prog_name,
- const gchar *pid);
-
-
int
main (int argc,
@@ -61,10 +54,9 @@ main (int argc,
gchar *error;
GtkWidget *dialog;
- if (argc != 5 && argc != 6)
+ if (argc != 6)
{
- g_print ("Usage: gimpdebug-2.0 [PROGRAM] [PID] [REASON] [MESSAGE] [BT_FILE]\n\n"
- "Note: the backtrace file is optional and only used in Windows.\n");
+ g_print ("Usage: gimpdebug-2.0 [PROGRAM] [PID] [REASON] [MESSAGE] [BT_FILE]\n");
exit (EXIT_FAILURE);
}
@@ -75,15 +67,8 @@ main (int argc,
error = g_strdup_printf ("%s: %s", reason, message);
- if (argc == 6)
- {
- bt_file = argv[5];
- g_file_get_contents (bt_file, &trace, NULL, NULL);
- }
- else
- {
- trace = gimp_debug_get_stack_trace (program, pid);
- }
+ bt_file = argv[5];
+ g_file_get_contents (bt_file, &trace, NULL, NULL);
if (trace == NULL || strlen (trace) == 0)
exit (EXIT_FAILURE);
@@ -105,33 +90,3 @@ main (int argc,
exit (EXIT_SUCCESS);
}
-
-
-static gchar *
-gimp_debug_get_stack_trace (const gchar *full_prog_name,
- const gchar *pid)
-{
- gchar *trace = NULL;
-
- /* This works only on UNIX systems. On Windows, we'll have to find
- * another method, probably with DrMingW.
- */
-#if defined(G_OS_UNIX)
- const gchar *args[7] = { "gdb", "-batch", "-ex", "backtrace full",
- full_prog_name, pid, NULL };
- gchar *gdb_stdout;
-
- if (g_spawn_sync (NULL, (gchar **) args, NULL,
- G_SPAWN_SEARCH_PATH | G_SPAWN_STDERR_TO_DEV_NULL,
- NULL, NULL, &gdb_stdout, NULL, NULL, NULL))
- {
- trace = g_strdup (gdb_stdout);
- }
- else if (gdb_stdout)
- {
- g_free (gdb_stdout);
- }
-#endif
-
- return trace;
-}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]