main: call gjs_dumpstack on aborts and traps and optionally on segfaults
In order to debug issues triggered by JS code we might need to see the stack of it, this is not normally visible in static stack traces, thus we need to call gjs_dumpstack () before dying the process. Intercepting signals SIGABRT, SIGTRAP (needed for catching fatal glib errors) SIGFPE and SIGIOT by default, while introducing a new 'backtrace-segfaults' flag for the SHELL_DEBUG environment variable to do the same on SIGSEGV and SIGBUS (this is a precaution to avoid that we corrupt the stack for automatic errors trackers). In any case after dumping the stack we raise the signal again, in order to make the system aware of it. https://bugzilla.gnome.org/show_bug.cgi?id=789237
This commit is contained in:
parent
78d58deb5a
commit
f15650e060
62
src/main.c
62
src/main.c
@ -38,12 +38,14 @@ extern GType gnome_shell_plugin_get_type (void);
|
|||||||
|
|
||||||
static gboolean is_gdm_mode = FALSE;
|
static gboolean is_gdm_mode = FALSE;
|
||||||
static char *session_mode = NULL;
|
static char *session_mode = NULL;
|
||||||
|
static int caught_signal = 0;
|
||||||
|
|
||||||
#define DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER 1
|
#define DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER 1
|
||||||
#define DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER 4
|
#define DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER 4
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
SHELL_DEBUG_BACKTRACE_WARNINGS = 1,
|
SHELL_DEBUG_BACKTRACE_WARNINGS = 1,
|
||||||
|
SHELL_DEBUG_BACKTRACE_SEGFAULTS = 2,
|
||||||
};
|
};
|
||||||
static int _shell_debug;
|
static int _shell_debug;
|
||||||
|
|
||||||
@ -290,7 +292,8 @@ static void
|
|||||||
shell_init_debug (const char *debug_env)
|
shell_init_debug (const char *debug_env)
|
||||||
{
|
{
|
||||||
static const GDebugKey keys[] = {
|
static const GDebugKey keys[] = {
|
||||||
{ "backtrace-warnings", SHELL_DEBUG_BACKTRACE_WARNINGS }
|
{ "backtrace-warnings", SHELL_DEBUG_BACKTRACE_WARNINGS },
|
||||||
|
{ "backtrace-segfaults", SHELL_DEBUG_BACKTRACE_SEGFAULTS },
|
||||||
};
|
};
|
||||||
|
|
||||||
_shell_debug = g_parse_debug_string (debug_env, keys,
|
_shell_debug = g_parse_debug_string (debug_env, keys,
|
||||||
@ -328,6 +331,52 @@ shut_up (const char *domain,
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
dump_gjs_stack_alarm_sigaction (int signo,
|
||||||
|
siginfo_t *info,
|
||||||
|
void *data)
|
||||||
|
{
|
||||||
|
g_warning ("Failed to dump Javascript stack, got stuck");
|
||||||
|
|
||||||
|
raise (caught_signal);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
dump_gjs_stack_on_signal_handler (int signo)
|
||||||
|
{
|
||||||
|
/* Waiting at least 5 seconds for the dumpstack, if it fails, we raise the error */
|
||||||
|
struct sigaction sa;
|
||||||
|
|
||||||
|
caught_signal = signo;
|
||||||
|
memset (&sa, 0, sizeof (sigaction));
|
||||||
|
sigemptyset (&sa.sa_mask);
|
||||||
|
|
||||||
|
sa.sa_flags = SA_SIGINFO;
|
||||||
|
sa.sa_sigaction = dump_gjs_stack_alarm_sigaction;
|
||||||
|
|
||||||
|
sigaction (SIGALRM, &sa, NULL);
|
||||||
|
|
||||||
|
alarm (5);
|
||||||
|
gjs_dumpstack ();
|
||||||
|
alarm (0);
|
||||||
|
|
||||||
|
raise (signo);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
dump_gjs_stack_on_signal (int signo)
|
||||||
|
{
|
||||||
|
struct sigaction sa;
|
||||||
|
|
||||||
|
memset (&sa, 0, sizeof (sigaction));
|
||||||
|
sigemptyset (&sa.sa_mask);
|
||||||
|
|
||||||
|
sa.sa_flags = SA_RESETHAND;
|
||||||
|
sa.sa_handler = dump_gjs_stack_on_signal_handler;
|
||||||
|
|
||||||
|
sigaction (signo, &sa, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
list_modes (const char *option_name,
|
list_modes (const char *option_name,
|
||||||
const char *value,
|
const char *value,
|
||||||
@ -459,6 +508,17 @@ main (int argc, char **argv)
|
|||||||
|
|
||||||
shell_prefs_init ();
|
shell_prefs_init ();
|
||||||
|
|
||||||
|
dump_gjs_stack_on_signal (SIGABRT);
|
||||||
|
dump_gjs_stack_on_signal (SIGFPE);
|
||||||
|
dump_gjs_stack_on_signal (SIGIOT);
|
||||||
|
dump_gjs_stack_on_signal (SIGTRAP);
|
||||||
|
|
||||||
|
if ((_shell_debug & SHELL_DEBUG_BACKTRACE_SEGFAULTS))
|
||||||
|
{
|
||||||
|
dump_gjs_stack_on_signal (SIGBUS);
|
||||||
|
dump_gjs_stack_on_signal (SIGSEGV);
|
||||||
|
}
|
||||||
|
|
||||||
ecode = meta_run ();
|
ecode = meta_run ();
|
||||||
|
|
||||||
g_debug ("Doing final cleanup");
|
g_debug ("Doing final cleanup");
|
||||||
|
Loading…
Reference in New Issue
Block a user