Browse Source

Add debug mode to run plugins in gdb.

With PANEL_DEBUG=gdb plugin will be started in gdb
and log files (with backtrace and register dump) are
automatically stored in /tmp.
Some functionality will not be available, like
automatically restart the plugins.

Also cleanup the debug level handling a bit, so it is
easier to extend and make struts debugging work again.
upstream/xfce4-panel-4.10.1
Nick Schermer 12 years ago
parent
commit
dc8625abcd
  1. 54
      common/panel-debug.c
  2. 9
      common/panel-debug.h
  3. 67
      panel/panel-plugin-external.c
  4. 2
      panel/panel-window.c

54
common/panel-debug.c

@ -28,16 +28,17 @@
#include <common/panel-debug.h>
#include <common/panel-private.h>
enum
{
DEBUG_LEVEL_UNKNOWN = 0,
DEBUG_LEVEL_NONE,
DEBUG_LEVEL_ENABLED
};
PanelDebugFlag panel_debug_flags = 0;
gboolean panel_debug_enabled = FALSE;
/* additional debug levels */
static const GDebugKey panel_debug_keys[] =
{
{ "gdb", PANEL_DEBUG_GDB }
};
@ -46,10 +47,9 @@ panel_debug (const gchar *domain,
const gchar *message,
...)
{
static volatile gsize level__volatile = DEBUG_LEVEL_UNKNOWN;
gsize level;
static volatile gsize level__volatile = 0;
const gchar *value;
gchar *string;
gchar *string, *path;
va_list args;
panel_return_if_fail (domain != NULL);
@ -60,15 +60,37 @@ panel_debug (const gchar *domain,
{
value = g_getenv ("PANEL_DEBUG");
if (G_UNLIKELY (value != NULL))
level = DEBUG_LEVEL_ENABLED;
else
level = DEBUG_LEVEL_NONE;
g_once_init_leave (&level__volatile, level);
{
panel_debug_flags = g_parse_debug_string (value, panel_debug_keys,
G_N_ELEMENTS (panel_debug_keys));
/* always enable debug logging */
PANEL_SET_FLAG (panel_debug_flags, PANEL_DEBUG_YES);
/* TODO: only print this in the main application */
if (PANEL_HAS_FLAG (panel_debug_flags, PANEL_DEBUG_GDB))
{
path = g_find_program_in_path ("gdb");
if (G_LIKELY (path != NULL))
{
g_printerr (PACKAGE_NAME "(debug): running plugins with %s; "
"log files stored in '%s'\n", path, g_get_tmp_dir ());
g_free (path);
}
else
{
PANEL_UNSET_FLAG (panel_debug_flags, PANEL_DEBUG_GDB);
g_printerr (PACKAGE_NAME "(debug): gdb not found in PATH; mode disabled\n");
}
}
}
g_once_init_leave (&level__volatile, 1);
}
/* leave when debug is disabled */
if (level__volatile == DEBUG_LEVEL_NONE)
if (panel_debug_flags == 0)
return;
va_start (args, message);

9
common/panel-debug.h

@ -30,7 +30,14 @@
#define PANEL_DEBUG_BOOL(bool) ((bool) ? "true" : "false")
extern gboolean panel_debug_enabled;
typedef enum
{
PANEL_DEBUG_YES = 1 << 0, /* always enabled if PANEL_DEBUG is not %NULL */
PANEL_DEBUG_GDB = 1 << 1 /* run plugin through gdb */
}
PanelDebugFlag;
extern PanelDebugFlag panel_debug_flags;
void panel_debug (const gchar *domain,
const gchar *message,

67
panel/panel-plugin-external.c

@ -487,16 +487,71 @@ panel_plugin_external_child_ask_restart (PanelPluginExternal *external)
static void
panel_plugin_external_child_spawn (PanelPluginExternal *external)
{
gchar **argv;
GError *error = NULL;
gboolean succeed;
GPid pid;
gchar **argv, **dbg_argv, **tmp_argv;
GError *error = NULL;
gboolean succeed;
GPid pid;
gchar *gdb, *cmd_line;
guint i;
gint tmp_argc;
GTimeVal timestamp;
panel_return_if_fail (PANEL_IS_PLUGIN_EXTERNAL (external));
panel_return_if_fail (GTK_WIDGET_REALIZED (external));
/* set plugin specific arguments */
argv = (*PANEL_PLUGIN_EXTERNAL_GET_CLASS (external)->get_argv) (external, external->priv->arguments);
panel_return_if_fail (argv != NULL);
/* check debugging state */
if (G_UNLIKELY (PANEL_HAS_FLAG (panel_debug_flags, PANEL_DEBUG_GDB)))
{
gdb = g_find_program_in_path ("gdb");
if (G_LIKELY (gdb != NULL))
{
g_get_current_time (&timestamp);
cmd_line = g_strdup_printf ("%s -batch "
"-ex 'set logging file %s" G_DIR_SEPARATOR_S "%li-%s-%s.txt' "
"-ex 'set logging on' "
"-ex 'set pagination off' "
"-ex 'set logging redirect on' "
"-ex 'run' "
"-ex 'backtrace full' "
"-ex 'info registers' "
"-args",
gdb, g_get_tmp_dir (), timestamp.tv_sec,
panel_module_get_name (external->module),
argv[PLUGIN_ARGV_UNIQUE_ID]);
if (g_shell_parse_argv (cmd_line, &tmp_argc, &tmp_argv, &error))
{
dbg_argv = g_new0 (gchar *, tmp_argc + g_strv_length (argv) + 1);
for (i = 0; tmp_argv[i] != NULL; i++)
dbg_argv[i] = tmp_argv[i];
g_free (tmp_argv);
for (i = 0; argv[i] != NULL; i++)
dbg_argv[i + tmp_argc] = argv[i];
g_free (argv);
argv = dbg_argv;
}
else
{
panel_debug (PANEL_DEBUG_DOMAIN_EXTERNAL,
"%s-%d: Failed to parse the gdb command line: %s",
panel_module_get_name (external->module),
external->unique_id, error->message);
g_error_free (error);
return;
}
g_free (gdb);
g_free (cmd_line);
}
}
/* spawn the proccess */
succeed = gdk_spawn_on_screen (gtk_widget_get_screen (GTK_WIDGET (external)),
@ -505,9 +560,9 @@ panel_plugin_external_child_spawn (PanelPluginExternal *external)
NULL, &pid, &error);
panel_debug (PANEL_DEBUG_DOMAIN_EXTERNAL,
"%s-%s: child spawned; pid=%d, socket-id=%s",
"%s-%d: child spawned; pid=%d, argc=%d",
panel_module_get_name (external->module),
argv[PLUGIN_ARGV_UNIQUE_ID], pid, argv[PLUGIN_ARGV_SOCKET_ID]);
external->unique_id, pid, g_strv_length (argv));
if (G_LIKELY (succeed))
{

2
panel/panel-window.c

@ -1461,7 +1461,7 @@ panel_window_screen_struts_set (PanelWindow *window)
if (gdk_error_trap_pop () != 0)
g_critical ("Failed to set the struts");
if (panel_debug_enabled)
if (G_UNLIKELY (panel_debug_flags != 0))
{
if (struts[STRUT_LEFT] != 0)
n = STRUT_LEFT;

Loading…
Cancel
Save