app: add a "generate-backtrace" preference in GimpCoreConfig.

This will determine whether to output backtrace in a GUI and is disabled
by default on stable, and activated in dev builds. It is a bit redundant
with --stack-trace-mode option CLI and will take priority when enabled
since most people would run GIMP with a graphical interface anyway.
This commit is contained in:
Jehan
2018-01-26 01:55:54 +01:00
parent beede1718a
commit f8411a3d1f
8 changed files with 117 additions and 40 deletions

View File

@ -113,6 +113,7 @@ enum
PROP_EXPORT_METADATA_EXIF, PROP_EXPORT_METADATA_EXIF,
PROP_EXPORT_METADATA_XMP, PROP_EXPORT_METADATA_XMP,
PROP_EXPORT_METADATA_IPTC, PROP_EXPORT_METADATA_IPTC,
PROP_GENERATE_BACKTRACE,
/* ignored, only for backward compatibility: */ /* ignored, only for backward compatibility: */
PROP_INSTALL_COLORMAP, PROP_INSTALL_COLORMAP,
@ -654,6 +655,17 @@ gimp_core_config_class_init (GimpCoreConfigClass *klass)
FALSE, FALSE,
GIMP_PARAM_STATIC_STRINGS); GIMP_PARAM_STATIC_STRINGS);
GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_GENERATE_BACKTRACE,
"generate-backtrace",
"Try generating backtrace upon errors",
GENERATE_BACKTRACE_BLURB,
#ifdef GIMP_UNSTABLE
TRUE,
#else
FALSE,
#endif
GIMP_PARAM_STATIC_STRINGS);
/* only for backward compatibility: */ /* only for backward compatibility: */
GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_INSTALL_COLORMAP, GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_INSTALL_COLORMAP,
"install-colormap", "install-colormap",
@ -956,6 +968,9 @@ gimp_core_config_set_property (GObject *object,
case PROP_EXPORT_METADATA_IPTC: case PROP_EXPORT_METADATA_IPTC:
core_config->export_metadata_iptc = g_value_get_boolean (value); core_config->export_metadata_iptc = g_value_get_boolean (value);
break; break;
case PROP_GENERATE_BACKTRACE:
core_config->generate_backtrace = g_value_get_boolean (value);
break;
case PROP_INSTALL_COLORMAP: case PROP_INSTALL_COLORMAP:
case PROP_MIN_COLORS: case PROP_MIN_COLORS:
@ -1152,6 +1167,9 @@ gimp_core_config_get_property (GObject *object,
case PROP_EXPORT_METADATA_IPTC: case PROP_EXPORT_METADATA_IPTC:
g_value_set_boolean (value, core_config->export_metadata_iptc); g_value_set_boolean (value, core_config->export_metadata_iptc);
break; break;
case PROP_GENERATE_BACKTRACE:
g_value_set_boolean (value, core_config->generate_backtrace);
break;
case PROP_INSTALL_COLORMAP: case PROP_INSTALL_COLORMAP:
case PROP_MIN_COLORS: case PROP_MIN_COLORS:

View File

@ -98,6 +98,7 @@ struct _GimpCoreConfig
gboolean export_metadata_exif; gboolean export_metadata_exif;
gboolean export_metadata_xmp; gboolean export_metadata_xmp;
gboolean export_metadata_iptc; gboolean export_metadata_iptc;
gboolean generate_backtrace;
}; };
struct _GimpCoreConfigClass struct _GimpCoreConfigClass

View File

@ -210,6 +210,9 @@ _("Export XMP metadata by default.")
#define EXPORT_METADATA_IPTC_BLURB \ #define EXPORT_METADATA_IPTC_BLURB \
_("Export IPTC metadata by default.") _("Export IPTC metadata by default.")
#define GENERATE_BACKTRACE_BLURB \
_("Try generating debug data for bug reporting when appropriate.")
#define INITIAL_ZOOM_TO_FIT_BLURB \ #define INITIAL_ZOOM_TO_FIT_BLURB \
_("When enabled, this will ensure that the full image is visible after a " \ _("When enabled, this will ensure that the full image is visible after a " \
"file is opened, otherwise it will be displayed with a scale of 1:1.") "file is opened, otherwise it will be displayed with a scale of 1:1.")

View File

@ -1176,6 +1176,16 @@ prefs_dialog_new (Gimp *gimp,
_("Use OpenCL"), _("Use OpenCL"),
GTK_BOX (vbox2)); GTK_BOX (vbox2));
#ifdef G_OS_UNIX
vbox2 = prefs_frame_new (_("Debugging"), GTK_CONTAINER (vbox),
FALSE);
prefs_check_button_add (object, "generate-backtrace",
_("Try generating debug data for bug reporting when appropriate.\n"
"This will require \"gdb\" installed on your computer."),
GTK_BOX (vbox2));
#endif
/* Image Thumbnails */ /* Image Thumbnails */
vbox2 = prefs_frame_new (_("Image Thumbnails"), GTK_CONTAINER (vbox), FALSE); vbox2 = prefs_frame_new (_("Image Thumbnails"), GTK_CONTAINER (vbox), FALSE);

View File

@ -199,8 +199,14 @@ gimp_message_log_func (const gchar *log_domain,
GimpMessageSeverity severity = GIMP_MESSAGE_WARNING; GimpMessageSeverity severity = GIMP_MESSAGE_WARNING;
Gimp *gimp = data; Gimp *gimp = data;
gchar *trace = NULL; gchar *trace = NULL;
GimpCoreConfig *config = gimp->config;
gboolean generate_backtrace = FALSE;
if (flags & G_LOG_LEVEL_CRITICAL) g_object_get (G_OBJECT (config),
"generate-backtrace", &generate_backtrace,
NULL);
if (generate_backtrace && (flags & G_LOG_LEVEL_CRITICAL))
{ {
severity = GIMP_MESSAGE_ERROR; severity = GIMP_MESSAGE_ERROR;
@ -250,47 +256,87 @@ gimp_eek (const gchar *reason,
const gchar *message, const gchar *message,
gboolean use_handler) gboolean use_handler)
{ {
GimpCoreConfig *config = the_errors_gimp->config;
gboolean generate_backtrace = FALSE;
/* GIMP has 2 ways to handle termination signals and fatal errors: one
* is the stack trace mode which is set at start as command line
* option --stack-trace-mode, this won't change for the length of the
* session and outputs a trace in terminal; the other is set in
* preferences, outputs a trace in a GUI and can change anytime during
* the session.
* The GUI backtrace has priority if it is set.
*/
g_object_get (G_OBJECT (config),
"generate-backtrace", &generate_backtrace,
NULL);
#ifndef G_OS_WIN32 #ifndef G_OS_WIN32
g_printerr ("%s: %s: %s\n", gimp_filename_to_utf8 (full_prog_name), g_printerr ("%s: %s: %s\n", gimp_filename_to_utf8 (full_prog_name),
reason, message); reason, message);
if (use_handler) if (use_handler)
{ {
switch (stack_trace_mode) #ifdef G_OS_UNIX
if (generate_backtrace)
{ {
case GIMP_STACK_TRACE_NEVER: /* If enabled (it is disabled by default), the GUI preference
break; * takes precedence over the command line argument.
case GIMP_STACK_TRACE_QUERY:
/* Basically we don't have the "QUERY" case anymore, at least
* for now until I figure out something.
*/ */
case GIMP_STACK_TRACE_ALWAYS: gchar *args[6] = { "gimpdebug-2.0", full_prog_name, NULL,
{ (gchar *) reason, (gchar *) message, NULL };
#if defined(G_OS_UNIX) gchar pid[16];
gchar *args[6] = { "gimpdebug-2.0", full_prog_name, NULL, gint exit_status;
(gchar *) reason, (gchar *) message, NULL };
gchar pid[16];
gint exit_status;
g_snprintf (pid, 16, "%u", (guint) getpid ()); g_snprintf (pid, 16, "%u", (guint) getpid ());
args[2] = pid; args[2] = pid;
/* We don't care about any return value. If it fails, too /* We don't care about any return value. If it fails, too
* bad, we just won't have any stack trace. * bad, we just won't have any stack trace.
* We still need to use the sync() variant because we have * We still need to use the sync() variant because we have
* to keep GIMP up long enough for the debugger to get its * to keep GIMP up long enough for the debugger to get its
* trace. * trace.
*/ */
g_spawn_sync (NULL, args, NULL, g_spawn_sync (NULL, args, NULL,
G_SPAWN_SEARCH_PATH | G_SPAWN_STDERR_TO_DEV_NULL | G_SPAWN_STDOUT_TO_DEV_NULL, G_SPAWN_SEARCH_PATH | G_SPAWN_STDERR_TO_DEV_NULL | G_SPAWN_STDOUT_TO_DEV_NULL,
NULL, NULL, NULL, NULL, &exit_status, NULL); NULL, NULL, NULL, NULL, &exit_status, NULL);
}
else
#endif #endif
} {
break; switch (stack_trace_mode)
{
case GIMP_STACK_TRACE_NEVER:
break;
default: case GIMP_STACK_TRACE_QUERY:
break; {
sigset_t sigset;
sigemptyset (&sigset);
sigprocmask (SIG_SETMASK, &sigset, NULL);
if (the_errors_gimp)
gimp_gui_ungrab (the_errors_gimp);
g_on_error_query (full_prog_name);
}
break;
case GIMP_STACK_TRACE_ALWAYS:
{
sigset_t sigset;
sigemptyset (&sigset);
sigprocmask (SIG_SETMASK, &sigset, NULL);
g_on_error_stack_trace (full_prog_name);
}
break;
default:
break;
}
} }
} }
#else #else

View File

@ -540,7 +540,7 @@ main (int argc,
if (abort_message) if (abort_message)
app_abort (no_interface, abort_message); app_abort (no_interface, abort_message);
gimp_init_signal_handlers (stack_trace_mode); gimp_init_signal_handlers ();
if (system_gimprc) if (system_gimprc)
system_gimprc_file = g_file_new_for_commandline_arg (system_gimprc); system_gimprc_file = g_file_new_for_commandline_arg (system_gimprc);

View File

@ -25,6 +25,8 @@
#include "core/core-types.h" #include "core/core-types.h"
#include "core/gimp.h"
#include "errors.h" #include "errors.h"
#include "signals.h" #include "signals.h"
@ -35,7 +37,7 @@ static void gimp_sigfatal_handler (gint sig_num) G_GNUC_NORETURN;
void void
gimp_init_signal_handlers (GimpStackTraceMode stack_trace_mode) gimp_init_signal_handlers (void)
{ {
#ifndef G_OS_WIN32 #ifndef G_OS_WIN32
/* No use catching these on Win32, the user won't get any stack /* No use catching these on Win32, the user won't get any stack
@ -54,13 +56,10 @@ gimp_init_signal_handlers (GimpStackTraceMode stack_trace_mode)
gimp_signal_private (SIGABRT, gimp_sigfatal_handler, 0); gimp_signal_private (SIGABRT, gimp_sigfatal_handler, 0);
gimp_signal_private (SIGTERM, gimp_sigfatal_handler, 0); gimp_signal_private (SIGTERM, gimp_sigfatal_handler, 0);
if (stack_trace_mode != GIMP_STACK_TRACE_NEVER) /* these are handled by gimp_fatal_error() */
{ gimp_signal_private (SIGBUS, gimp_sigfatal_handler, 0);
/* these are handled by gimp_fatal_error() */ gimp_signal_private (SIGSEGV, gimp_sigfatal_handler, 0);
gimp_signal_private (SIGBUS, gimp_sigfatal_handler, 0); gimp_signal_private (SIGFPE, gimp_sigfatal_handler, 0);
gimp_signal_private (SIGSEGV, gimp_sigfatal_handler, 0);
gimp_signal_private (SIGFPE, gimp_sigfatal_handler, 0);
}
/* Ignore SIGPIPE because plug_in.c handles broken pipes */ /* Ignore SIGPIPE because plug_in.c handles broken pipes */
gimp_signal_private (SIGPIPE, SIG_IGN, 0); gimp_signal_private (SIGPIPE, SIG_IGN, 0);

View File

@ -23,7 +23,7 @@
#endif #endif
void gimp_init_signal_handlers (GimpStackTraceMode stack_trace_mode); void gimp_init_signal_handlers (void);
#endif /* __SIGNALS_H__ */ #endif /* __SIGNALS_H__ */