From 12ba2b222f4c23be39542443e93dff45405f1b70 Mon Sep 17 00:00:00 2001
From: Giovanni Campagna <gcampagna@src.gnome.org>
Date: Wed, 28 Nov 2012 19:45:52 +0100
Subject: [PATCH] Add a way to get backtraces from criticals and warnings

Attaching gdb and running with G_DEBUG=fatal-warnings is not a very
fast to debug a specific issue (especially if you have warnings at
startup, since then you need to run the shell from a terminal).
Instead, introduce a new SHELL_DEBUG environment variable that can
be set to backtrace-warning, causing a gjs_dumpstack() after every
warning or critical.

https://bugzilla.gnome.org/show_bug.cgi?id=700262
---
 src/main.c | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/src/main.c b/src/main.c
index ca2116a96..25d708d6d 100644
--- a/src/main.c
+++ b/src/main.c
@@ -47,6 +47,11 @@ static char *session_mode = NULL;
 #define DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER 1
 #define DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER 4
 
+enum {
+  SHELL_DEBUG_BACKTRACE_WARNINGS = 1,
+};
+static int _shell_debug;
+
 static void
 shell_dbus_acquire_name (GDBusProxy *bus,
                          guint32     request_name_flags,
@@ -269,6 +274,17 @@ shell_a11y_init (void)
     }
 }
 
+static void
+shell_init_debug (const char *debug_env)
+{
+  static const GDebugKey keys[] = {
+    { "backtrace-warnings", SHELL_DEBUG_BACKTRACE_WARNINGS }
+  };
+
+  _shell_debug = g_parse_debug_string (debug_env, keys,
+                                       G_N_ELEMENTS (keys));
+}
+
 static void
 default_log_handler (const char     *log_domain,
                      GLogLevelFlags  log_level,
@@ -286,6 +302,15 @@ default_log_handler (const char     *log_domain,
    * with those. */
   if (!log_domain || !g_str_has_prefix (log_domain, "tp-glib"))
     g_log_default_handler (log_domain, log_level, message, data);
+
+  /* Filter out Gjs logs, those already have the stack */
+  if (log_domain && strcmp (log_domain, "Gjs") == 0)
+    return;
+
+  if ((_shell_debug & SHELL_DEBUG_BACKTRACE_WARNINGS) &&
+      ((log_level & G_LOG_LEVEL_CRITICAL) ||
+       (log_level & G_LOG_LEVEL_WARNING)))
+    gjs_dumpstack ();
 }
 
 static void
@@ -406,6 +431,8 @@ main (int argc, char **argv)
   g_setenv ("GJS_DEBUG_OUTPUT", "stderr", TRUE);
   g_setenv ("GJS_DEBUG_TOPICS", "JS ERROR;JS LOG", TRUE);
 
+  shell_init_debug (g_getenv ("SHELL_DEBUG"));
+
   shell_dbus_init (meta_get_replace_current_wm ());
   shell_a11y_init ();
   shell_perf_log_init ();
@@ -419,6 +446,7 @@ main (int argc, char **argv)
   tp_debug_set_flags ("all");
 
   sender = tp_debug_sender_dup ();
+
   g_log_set_default_handler (default_log_handler, sender);
 
   /* Initialize the global object */