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_XMP,
PROP_EXPORT_METADATA_IPTC,
PROP_GENERATE_BACKTRACE,
/* ignored, only for backward compatibility: */
PROP_INSTALL_COLORMAP,
@ -654,6 +655,17 @@ gimp_core_config_class_init (GimpCoreConfigClass *klass)
FALSE,
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: */
GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_INSTALL_COLORMAP,
"install-colormap",
@ -956,6 +968,9 @@ gimp_core_config_set_property (GObject *object,
case PROP_EXPORT_METADATA_IPTC:
core_config->export_metadata_iptc = g_value_get_boolean (value);
break;
case PROP_GENERATE_BACKTRACE:
core_config->generate_backtrace = g_value_get_boolean (value);
break;
case PROP_INSTALL_COLORMAP:
case PROP_MIN_COLORS:
@ -1152,6 +1167,9 @@ gimp_core_config_get_property (GObject *object,
case PROP_EXPORT_METADATA_IPTC:
g_value_set_boolean (value, core_config->export_metadata_iptc);
break;
case PROP_GENERATE_BACKTRACE:
g_value_set_boolean (value, core_config->generate_backtrace);
break;
case PROP_INSTALL_COLORMAP:
case PROP_MIN_COLORS:

View file

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

View file

@ -210,6 +210,9 @@ _("Export XMP metadata by default.")
#define EXPORT_METADATA_IPTC_BLURB \
_("Export IPTC metadata by default.")
#define GENERATE_BACKTRACE_BLURB \
_("Try generating debug data for bug reporting when appropriate.")
#define INITIAL_ZOOM_TO_FIT_BLURB \
_("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.")

View file

@ -1176,6 +1176,16 @@ prefs_dialog_new (Gimp *gimp,
_("Use OpenCL"),
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 */
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;
Gimp *gimp = data;
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;
@ -250,47 +256,87 @@ gimp_eek (const gchar *reason,
const gchar *message,
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
g_printerr ("%s: %s: %s\n", gimp_filename_to_utf8 (full_prog_name),
reason, message);
if (use_handler)
{
switch (stack_trace_mode)
#ifdef G_OS_UNIX
if (generate_backtrace)
{
case GIMP_STACK_TRACE_NEVER:
break;
case GIMP_STACK_TRACE_QUERY:
/* Basically we don't have the "QUERY" case anymore, at least
* for now until I figure out something.
/* If enabled (it is disabled by default), the GUI preference
* takes precedence over the command line argument.
*/
case GIMP_STACK_TRACE_ALWAYS:
{
#if defined(G_OS_UNIX)
gchar *args[6] = { "gimpdebug-2.0", full_prog_name, NULL,
(gchar *) reason, (gchar *) message, NULL };
gchar pid[16];
gint exit_status;
gchar *args[6] = { "gimpdebug-2.0", full_prog_name, NULL,
(gchar *) reason, (gchar *) message, NULL };
gchar pid[16];
gint exit_status;
g_snprintf (pid, 16, "%u", (guint) getpid ());
args[2] = pid;
g_snprintf (pid, 16, "%u", (guint) getpid ());
args[2] = pid;
/* 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.
*/
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, &exit_status, NULL);
/* 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.
*/
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, &exit_status, NULL);
}
else
#endif
}
break;
{
switch (stack_trace_mode)
{
case GIMP_STACK_TRACE_NEVER:
break;
default:
break;
case GIMP_STACK_TRACE_QUERY:
{
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

View file

@ -540,7 +540,7 @@ main (int argc,
if (abort_message)
app_abort (no_interface, abort_message);
gimp_init_signal_handlers (stack_trace_mode);
gimp_init_signal_handlers ();
if (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/gimp.h"
#include "errors.h"
#include "signals.h"
@ -35,7 +37,7 @@ static void gimp_sigfatal_handler (gint sig_num) G_GNUC_NORETURN;
void
gimp_init_signal_handlers (GimpStackTraceMode stack_trace_mode)
gimp_init_signal_handlers (void)
{
#ifndef G_OS_WIN32
/* 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 (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);
gimp_signal_private (SIGSEGV, gimp_sigfatal_handler, 0);
gimp_signal_private (SIGFPE, gimp_sigfatal_handler, 0);
}
/* these are handled by gimp_fatal_error() */
gimp_signal_private (SIGBUS, 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 */
gimp_signal_private (SIGPIPE, SIG_IGN, 0);

View file

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