[gnome-shell/dynamic-debug-flags: 1/2] global: make possible to set debug-flags dynamically



commit 1a2f88d3116715bf5b641a5d3dda642c938613fa
Author: Marco Trevisan (TreviƱo) <mail 3v1n0 net>
Date:   Mon Oct 23 19:15:13 2017 -0500

    global: make possible to set debug-flags dynamically
    
    Adding {set,get}_debug_flags functions to the shell global object to
    make possible to set this easily from looking class, making it easier
    for developers and users to debug without having to restart the shell
    with environment variables.
    
    Debug flags in main are updated when the "debug-flags" property is
    changed. I'm keeping this as a string-list so that it's easier to update.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=789377

 src/main.c         | 62 ++++++++++++++++++++++++++++++++++++++++++------------
 src/shell-global.c | 52 +++++++++++++++++++++++++++++++++++++++++++++
 src/shell-global.h |  3 +++
 3 files changed, 103 insertions(+), 14 deletions(-)
---
diff --git a/src/main.c b/src/main.c
index 934fbd566..3b6d7323c 100644
--- a/src/main.c
+++ b/src/main.c
@@ -290,14 +290,14 @@ shell_a11y_init (void)
 }
 
 static void
-shell_init_debug (const char *debug_env)
+shell_update_debug (const char *debug_string)
 {
   static const GDebugKey keys[] = {
     { "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_string, keys,
                                        G_N_ELEMENTS (keys));
 }
 
@@ -385,6 +385,42 @@ dump_gjs_stack_on_signal (int signo)
   _tracked_signals[signo] = TRUE;
 }
 
+static void
+reset_signal_handler_to_default (int signo)
+{
+  signal (signo, SIG_DFL);
+  _tracked_signals[signo] = FALSE;
+}
+
+static void
+setup_debug_signal_listners (void)
+{
+  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);
+    }
+  else
+    {
+      reset_signal_handler_to_default (SIGBUS);
+      reset_signal_handler_to_default (SIGSEGV);
+    }
+}
+
+static void
+global_notify_debug_flags (GObject    *gobject,
+                           GParamSpec *pspec,
+                           gpointer    data)
+{
+  shell_update_debug (shell_global_get_debug_flags (shell_global_get ()));
+  setup_debug_signal_listners ();
+}
+
 static gboolean
 list_modes (const char  *option_name,
             const char  *value,
@@ -463,6 +499,7 @@ main (int argc, char **argv)
 {
   GOptionContext *ctx;
   GError *error = NULL;
+  const char *debug_flags;
   int ecode;
 
   bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
@@ -498,7 +535,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"));
+  debug_flags = g_getenv ("SHELL_DEBUG");
+  shell_update_debug (debug_flags);
 
   shell_dbus_init (meta_get_replace_current_wm ());
   shell_a11y_init ();
@@ -512,20 +550,16 @@ main (int argc, char **argv)
   if (session_mode == NULL)
     session_mode = is_gdm_mode ? (char *)"gdm" : (char *)"user";
 
-  _shell_global_init ("session-mode", session_mode, NULL);
+  _shell_global_init ("session-mode", session_mode,
+                      "debug-flags", debug_flags,
+                      NULL);
 
-  shell_prefs_init ();
+  g_signal_connect (shell_global_get (), "notify::debug-flags",
+                    G_CALLBACK (global_notify_debug_flags), NULL);
 
-  dump_gjs_stack_on_signal (SIGABRT);
-  dump_gjs_stack_on_signal (SIGFPE);
-  dump_gjs_stack_on_signal (SIGIOT);
-  dump_gjs_stack_on_signal (SIGTRAP);
+  shell_prefs_init ();
 
-  if ((_shell_debug & SHELL_DEBUG_BACKTRACE_SEGFAULTS))
-    {
-      dump_gjs_stack_on_signal (SIGBUS);
-      dump_gjs_stack_on_signal (SIGSEGV);
-    }
+  setup_debug_signal_listners ();
 
   ecode = meta_run ();
 
diff --git a/src/shell-global.c b/src/shell-global.c
index 855f6257c..5ef8dec8e 100644
--- a/src/shell-global.c
+++ b/src/shell-global.c
@@ -67,6 +67,7 @@ struct _ShellGlobal {
   GdkScreen *gdk_screen;
 
   char *session_mode;
+  char *debug_flags;
 
   XserverRegion input_region;
 
@@ -114,6 +115,7 @@ enum {
   PROP_FOCUS_MANAGER,
   PROP_FRAME_TIMESTAMPS,
   PROP_FRAME_FINISH_TIMESTAMP,
+  PROP_DEBUG_FLAGS,
 };
 
 /* Signals */
@@ -147,6 +149,9 @@ shell_global_set_property(GObject         *object,
     case PROP_FRAME_FINISH_TIMESTAMP:
       global->frame_finish_timestamp = g_value_get_boolean (value);
       break;
+    case PROP_DEBUG_FLAGS:
+      shell_global_set_debug_flags (global, g_value_get_string (value));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -224,6 +229,9 @@ shell_global_get_property(GObject         *object,
     case PROP_FRAME_FINISH_TIMESTAMP:
       g_value_set_boolean (value, global->frame_finish_timestamp);
       break;
+    case PROP_DEBUG_FLAGS:
+      g_value_set_string (value, global->debug_flags);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -490,6 +498,13 @@ shell_global_class_init (ShellGlobalClass *klass)
                                                          "Whether at the end of a frame to call glFinish and 
log paintCompletedTimestamp",
                                                          FALSE,
                                                          G_PARAM_READWRITE));
+  g_object_class_install_property (gobject_class,
+                                   PROP_DEBUG_FLAGS,
+                                   g_param_spec_string ("debug-flags",
+                                                        "Debug Flags",
+                                                        "The debugging flags",
+                                                        NULL,
+                                                        G_PARAM_READWRITE));
 }
 
 /*
@@ -2015,3 +2030,40 @@ shell_global_get_persistent_state (ShellGlobal  *global,
 {
   return load_variant (global->userdatadir_path, property_type, property_name);
 }
+
+/**
+ * shell_global_get_debug_flags:
+ * @global: a #ShellGlobal
+ *
+ * Returns: (transfer none): The current debug flags
+ */
+const gchar *
+shell_global_get_debug_flags (ShellGlobal *global)
+{
+  g_return_if_fail (SHELL_IS_GLOBAL (global));
+
+  return global->debug_flags;
+}
+
+/**
+ * shell_global_set_debug_flags:
+ * @global: a #ShellGlobal
+ * @debug_flags: (nullable): A string for debugging flags
+ *
+ * Updates the debugging flags at runtime as the one set using the SHELL_DEBUG
+ * environment variables. Currently we support 'backtrace-warnings' and
+ * 'backtrace-segfaults' keys.
+ */
+void
+shell_global_set_debug_flags (ShellGlobal  *global,
+                              const char   *debug_flags)
+{
+  g_return_if_fail (SHELL_IS_GLOBAL (global));
+
+  if (g_strcmp0 (global->debug_flags, debug_flags) != 0)
+    {
+      g_free (global->debug_flags);
+      global->debug_flags = g_strdup (debug_flags);
+      g_object_notify (G_OBJECT (global), "debug-flags");
+    }
+}
diff --git a/src/shell-global.h b/src/shell-global.h
index 47c441553..e37f3c686 100644
--- a/src/shell-global.h
+++ b/src/shell-global.h
@@ -128,6 +128,9 @@ void     shell_global_set_persistent_state      (ShellGlobal  *global,
 GVariant * shell_global_get_persistent_state    (ShellGlobal  *global,
                                                  const char   *property_type,
                                                  const char   *property_name);
+const char * shell_global_get_debug_flags       (ShellGlobal  *global);
+void     shell_global_set_debug_flags           (ShellGlobal  *global,
+                                                 const char   *debug_flags);
 
 G_END_DECLS
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]