[gdm] Add an X11 error trap mechanism
- From: William Jon McCann <mccann src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gdm] Add an X11 error trap mechanism
- Date: Wed, 16 Jun 2010 22:48:59 +0000 (UTC)
commit 23d5ed6b9ccbffbfb76e4551cce9051eea62cc52
Author: William Jon McCann <jmccann redhat com>
Date: Wed Jun 16 18:41:49 2010 -0400
Add an X11 error trap mechanism
Copied from GDK
daemon/Makefile.am | 8 ++
daemon/factory-slave-main.c | 2 +
daemon/gdm-slave.c | 1 +
daemon/gdm-xerrors.c | 242 +++++++++++++++++++++++++++++++++++++
daemon/gdm-xerrors.h | 39 ++++++
daemon/product-slave-main.c | 2 +
daemon/simple-slave-main.c | 2 +
daemon/xdmcp-chooser-slave-main.c | 2 +
8 files changed, 298 insertions(+), 0 deletions(-)
---
diff --git a/daemon/Makefile.am b/daemon/Makefile.am
index fed212f..731a041 100644
--- a/daemon/Makefile.am
+++ b/daemon/Makefile.am
@@ -134,6 +134,8 @@ gdm_simple_slave_SOURCES = \
gdm-session-record.h \
gdm-session-worker-job.c \
gdm-session-worker-job.h \
+ gdm-xerrors.h \
+ gdm-xerrors.c \
gdm-slave.c \
gdm-slave.h \
gdm-simple-slave.c \
@@ -169,6 +171,8 @@ gdm_factory_slave_SOURCES = \
gdm-session-private.h \
gdm-session-relay.c \
gdm-session-relay.h \
+ gdm-xerrors.h \
+ gdm-xerrors.c \
gdm-slave.c \
gdm-slave.h \
gdm-factory-slave.c \
@@ -198,6 +202,8 @@ gdm_product_slave_SOURCES = \
gdm-session-record.h \
gdm-session-worker-job.c \
gdm-session-worker-job.h \
+ gdm-xerrors.h \
+ gdm-xerrors.c \
gdm-slave.c \
gdm-slave.h \
gdm-product-slave.c \
@@ -226,6 +232,8 @@ gdm_xdmcp_chooser_slave_SOURCES = \
gdm-welcome-session.h \
gdm-chooser-session.c \
gdm-chooser-session.h \
+ gdm-xerrors.h \
+ gdm-xerrors.c \
gdm-slave.c \
gdm-slave.h \
gdm-xdmcp-chooser-slave.c \
diff --git a/daemon/factory-slave-main.c b/daemon/factory-slave-main.c
index 8a99749..832dc4f 100644
--- a/daemon/factory-slave-main.c
+++ b/daemon/factory-slave-main.c
@@ -39,6 +39,7 @@
#include <dbus/dbus-glib.h>
#include <dbus/dbus-glib-lowlevel.h>
+#include "gdm-xerrors.h"
#include "gdm-signal-handler.h"
#include "gdm-log.h"
#include "gdm-common.h"
@@ -197,6 +198,7 @@ main (int argc,
goto out;
}
+ gdm_xerrors_init ();
gdm_log_init ();
settings = gdm_settings_new ();
diff --git a/daemon/gdm-slave.c b/daemon/gdm-slave.c
index 4532758..b7a0c0c 100644
--- a/daemon/gdm-slave.c
+++ b/daemon/gdm-slave.c
@@ -47,6 +47,7 @@
#include <X11/Xatom.h>
#include "gdm-common.h"
+#include "gdm-xerrors.h"
#include "gdm-slave.h"
#include "gdm-slave-glue.h"
diff --git a/daemon/gdm-xerrors.c b/daemon/gdm-xerrors.c
new file mode 100644
index 0000000..90e6ad6
--- /dev/null
+++ b/daemon/gdm-xerrors.c
@@ -0,0 +1,242 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2010 William Jon McCann <jmccann redhat com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+/* Most of this is derived from GTK+ (copyright GTK+ team) */
+
+#include <glib.h>
+#include <glib/gstdio.h>
+#include <errno.h>
+#include <stdlib.h>
+
+#include "gdm-xerrors.h"
+
+typedef struct _GdmErrorTrap GdmErrorTrap;
+
+struct _GdmErrorTrap
+{
+ int (*old_handler) (Display *, XErrorEvent *);
+ int error_warnings;
+ int error_code;
+};
+
+static int gdm_x_error (Display *display,
+ XErrorEvent *error);
+static int gdm_x_io_error (Display *display);
+
+/* Private variable declarations
+ */
+static GSList *gdm_error_traps = NULL; /* List of error traps */
+static GSList *gdm_error_trap_free_list = NULL; /* Free list */
+
+static int _gdm_error_warnings = TRUE;
+static int _gdm_error_code = 0;
+
+void
+gdm_xerrors_init (void)
+{
+ static gboolean initialized = FALSE;
+
+ if (initialized) {
+ return;
+ }
+
+ XSetErrorHandler (gdm_x_error);
+ XSetIOErrorHandler (gdm_x_io_error);
+ initialized = TRUE;
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdm_x_error
+ *
+ * The X error handling routine.
+ *
+ * Arguments:
+ * "display" is the X display the error orignated from.
+ * "error" is the XErrorEvent that we are handling.
+ *
+ * Results:
+ * Either we were expecting some sort of error to occur,
+ * in which case we set the "_gdm_error_code" flag, or this
+ * error was unexpected, in which case we will print an
+ * error message and exit. (Since trying to continue will
+ * most likely simply lead to more errors).
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+gdm_x_error (Display *display,
+ XErrorEvent *error)
+{
+ if (error->error_code) {
+ if (_gdm_error_warnings) {
+ gchar buf[64];
+ gchar *msg;
+
+ XGetErrorText (display, error->error_code, buf, 63);
+
+ msg =
+ g_strdup_printf ("The program '%s' received an X Window System error.\n"
+ "This probably reflects a bug in the program.\n"
+ "The error was '%s'.\n"
+ " (Details: serial %ld error_code %d request_code %d minor_code %d)\n"
+ " (Note to programmers: normally, X errors are reported asynchronously;\n"
+ " that is, you will receive the error a while after causing it.\n"
+ " To debug your program, run it with the --sync command line\n"
+ " option to change this behavior. You can then get a meaningful\n"
+ " backtrace from your debugger if you break on the gdm_x_error() function.)",
+ g_get_prgname (),
+ buf,
+ error->serial,
+ error->error_code,
+ error->request_code,
+ error->minor_code);
+
+#ifdef G_ENABLE_DEBUG
+ g_error ("%s", msg);
+#else /* !G_ENABLE_DEBUG */
+ g_fprintf (stderr, "%s\n", msg);
+
+ exit (1);
+#endif /* G_ENABLE_DEBUG */
+ }
+ _gdm_error_code = error->error_code;
+ }
+
+ return 0;
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdm_x_io_error
+ *
+ * The X I/O error handling routine.
+ *
+ * Arguments:
+ * "display" is the X display the error orignated from.
+ *
+ * Results:
+ * An X I/O error basically means we lost our connection
+ * to the X server. There is not much we can do to
+ * continue, so simply print an error message and exit.
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+gdm_x_io_error (Display *display)
+{
+ /* This is basically modelled after the code in XLib. We need
+ * an explicit error handler here, so we can disable our atexit()
+ * which would otherwise cause a nice segfault.
+ * We fprintf(stderr, instead of g_warning() because g_warning()
+ * could possibly be redirected to a dialog
+ */
+ if (errno == EPIPE) {
+ g_fprintf (stderr,
+ "The application '%s' lost its connection to the display %s;\n"
+ "most likely the X server was shut down or you killed/destroyed\n"
+ "the application.\n",
+ g_get_prgname (),
+ display ? DisplayString (display) : "<unknown>");
+ } else {
+ g_fprintf (stderr, "%s: Fatal IO error %d (%s) on X server %s.\n",
+ g_get_prgname (),
+ errno, g_strerror (errno),
+ display ? DisplayString (display) : "<unknown>");
+ }
+
+ exit(1);
+}
+
+/*************************************************************
+ * gdm_error_trap_push:
+ * Push an error trap. X errors will be trapped until
+ * the corresponding gdm_error_pop(), which will return
+ * the error code, if any.
+ * arguments:
+ *
+ * results:
+ *************************************************************/
+
+void
+gdm_error_trap_push (void)
+{
+ GSList *node;
+ GdmErrorTrap *trap;
+
+ if (gdm_error_trap_free_list) {
+ node = gdm_error_trap_free_list;
+ gdm_error_trap_free_list = gdm_error_trap_free_list->next;
+ } else {
+ node = g_slist_alloc ();
+ node->data = g_new (GdmErrorTrap, 1);
+ }
+
+ node->next = gdm_error_traps;
+ gdm_error_traps = node;
+
+ trap = node->data;
+ trap->old_handler = XSetErrorHandler (gdm_x_error);
+ trap->error_code = _gdm_error_code;
+ trap->error_warnings = _gdm_error_warnings;
+
+ _gdm_error_code = 0;
+ _gdm_error_warnings = 0;
+}
+
+/*************************************************************
+ * gdm_error_trap_pop:
+ * Pop an error trap added with gdm_error_push()
+ * arguments:
+ *
+ * results:
+ * 0, if no error occured, otherwise the error code.
+ *************************************************************/
+
+gint
+gdm_error_trap_pop (void)
+{
+ GSList *node;
+ GdmErrorTrap *trap;
+ gint result;
+
+ g_return_val_if_fail (gdm_error_traps != NULL, 0);
+
+ node = gdm_error_traps;
+ gdm_error_traps = gdm_error_traps->next;
+
+ node->next = gdm_error_trap_free_list;
+ gdm_error_trap_free_list = node;
+
+ result = _gdm_error_code;
+
+ trap = node->data;
+ _gdm_error_code = trap->error_code;
+ _gdm_error_warnings = trap->error_warnings;
+ XSetErrorHandler (trap->old_handler);
+
+ return result;
+}
diff --git a/daemon/gdm-xerrors.h b/daemon/gdm-xerrors.h
new file mode 100644
index 0000000..16efca3
--- /dev/null
+++ b/daemon/gdm-xerrors.h
@@ -0,0 +1,39 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+
+/* Metacity X error handling */
+
+/*
+ * Copyright (C) 2001 Havoc Pennington
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef GDM_XERRORS_H
+#define GDM_XERRORS_H
+
+#include <glib.h>
+#include <X11/Xlib.h>
+
+typedef void (* GdmXErrorHandler) (Display *dpy,
+ XErrorEvent *error,
+ gpointer data);
+
+void gdm_xerrors_init (void);
+
+void gdm_error_trap_push (void);
+gint gdm_error_trap_pop (void);
+
+#endif
diff --git a/daemon/product-slave-main.c b/daemon/product-slave-main.c
index b696ad2..7353f3a 100644
--- a/daemon/product-slave-main.c
+++ b/daemon/product-slave-main.c
@@ -39,6 +39,7 @@
#include <dbus/dbus-glib.h>
#include <dbus/dbus-glib-lowlevel.h>
+#include "gdm-xerrors.h"
#include "gdm-signal-handler.h"
#include "gdm-log.h"
#include "gdm-common.h"
@@ -201,6 +202,7 @@ main (int argc,
goto out;
}
+ gdm_xerrors_init ();
gdm_log_init ();
settings = gdm_settings_new ();
diff --git a/daemon/simple-slave-main.c b/daemon/simple-slave-main.c
index e9d65ee..eed1742 100644
--- a/daemon/simple-slave-main.c
+++ b/daemon/simple-slave-main.c
@@ -39,6 +39,7 @@
#include <dbus/dbus-glib.h>
#include <dbus/dbus-glib-lowlevel.h>
+#include "gdm-xerrors.h"
#include "gdm-signal-handler.h"
#include "gdm-log.h"
#include "gdm-common.h"
@@ -204,6 +205,7 @@ main (int argc,
goto out;
}
+ gdm_xerrors_init ();
gdm_log_init ();
settings = gdm_settings_new ();
diff --git a/daemon/xdmcp-chooser-slave-main.c b/daemon/xdmcp-chooser-slave-main.c
index a35c978..0b68af1 100644
--- a/daemon/xdmcp-chooser-slave-main.c
+++ b/daemon/xdmcp-chooser-slave-main.c
@@ -39,6 +39,7 @@
#include <dbus/dbus-glib.h>
#include <dbus/dbus-glib-lowlevel.h>
+#include "gdm-xerrors.h"
#include "gdm-signal-handler.h"
#include "gdm-log.h"
#include "gdm-common.h"
@@ -203,6 +204,7 @@ main (int argc,
goto out;
}
+ gdm_xerrors_init ();
gdm_log_init ();
settings = gdm_settings_new ();
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]