mtk: Make error traps multi-display

Keep a per-display list of error traps, so we don't mix them
together, and possibly deem unintended error traps outdated.

This means init/deinit calls are now stackable, and need to
happen evenly. In order to honor this, move the MetaX11Display
error trap destrution to finalize.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3230>
This commit is contained in:
Carlos Garnacho 2023-09-01 01:14:21 +02:00 committed by Marge Bot
parent 6f46edd93b
commit ef366c5fcb
2 changed files with 50 additions and 9 deletions

View File

@ -54,7 +54,8 @@ typedef int (* MtkXErrorHandler) (Display *, XErrorEvent *);
static MtkXErrorHandler old_error_handler = NULL; static MtkXErrorHandler old_error_handler = NULL;
/* number of times we've pushed the error handler */ /* number of times we've pushed the error handler */
static int error_handler_push_count = 0; static int error_handler_push_count = 0;
static GList *error_traps = NULL; static GHashTable *display_error_traps = NULL;
static int init_count = 0;
/* look up the extension name for a given major opcode. grubs around in /* look up the extension name for a given major opcode. grubs around in
* xlib to do it since a) its already cached there b) XQueryExtension * xlib to do it since a) its already cached there b) XQueryExtension
@ -84,6 +85,9 @@ display_error_event (Display *xdisplay,
{ {
GList *l; GList *l;
gboolean ignore = FALSE; gboolean ignore = FALSE;
GList *error_traps;
error_traps = g_hash_table_lookup (display_error_traps, xdisplay);
for (l = error_traps; l; l = l->next) for (l = error_traps; l; l = l->next)
{ {
@ -172,11 +176,12 @@ error_handler_pop (void)
static void static void
delete_outdated_error_traps (Display *xdisplay) delete_outdated_error_traps (Display *xdisplay)
{ {
GList *l; GList *l, *error_traps;
unsigned long processed_sequence; unsigned long processed_sequence;
processed_sequence = XLastKnownRequestProcessed (xdisplay); processed_sequence = XLastKnownRequestProcessed (xdisplay);
l = error_traps; l = error_traps = g_hash_table_lookup (display_error_traps, xdisplay);
g_hash_table_steal (display_error_traps, xdisplay);
while (l != NULL) while (l != NULL)
{ {
@ -196,6 +201,14 @@ delete_outdated_error_traps (Display *xdisplay)
l = l->next; l = l->next;
} }
} }
g_hash_table_insert (display_error_traps, xdisplay, error_traps);
}
static void
free_trap_list (gpointer data)
{
g_list_free_full (data, g_free);
} }
/** /**
@ -204,7 +217,14 @@ delete_outdated_error_traps (Display *xdisplay)
void void
mtk_x11_errors_init (void) mtk_x11_errors_init (void)
{ {
XSetErrorHandler (mtk_x_error); if (init_count == 0)
{
XSetErrorHandler (mtk_x_error);
display_error_traps =
g_hash_table_new_full (NULL, NULL, NULL, free_trap_list);
}
init_count++;
} }
/** /**
@ -213,8 +233,14 @@ mtk_x11_errors_init (void)
void void
mtk_x11_errors_deinit (void) mtk_x11_errors_deinit (void)
{ {
g_clear_list (&error_traps, g_free); init_count--;
XSetErrorHandler (NULL); g_assert (init_count >= 0);
if (init_count == 0)
{
g_clear_pointer (&display_error_traps, g_hash_table_unref);
XSetErrorHandler (NULL);
}
} }
/** /**
@ -224,6 +250,7 @@ void
mtk_x11_error_trap_push (Display *xdisplay) mtk_x11_error_trap_push (Display *xdisplay)
{ {
MtkErrorTrap *trap; MtkErrorTrap *trap;
GList *error_traps;
delete_outdated_error_traps (xdisplay); delete_outdated_error_traps (xdisplay);
@ -234,7 +261,10 @@ mtk_x11_error_trap_push (Display *xdisplay)
trap->start_sequence = XNextRequest (xdisplay); trap->start_sequence = XNextRequest (xdisplay);
trap->error_code = Success; trap->error_code = Success;
error_traps = g_hash_table_lookup (display_error_traps, xdisplay);
g_hash_table_steal (display_error_traps, xdisplay);
error_traps = g_list_prepend (error_traps, trap); error_traps = g_list_prepend (error_traps, trap);
g_hash_table_insert (display_error_traps, xdisplay, error_traps);
} }
static int static int
@ -242,9 +272,11 @@ mtk_x11_error_trap_pop_internal (Display *xdisplay,
gboolean need_code) gboolean need_code)
{ {
MtkErrorTrap *trap = NULL; MtkErrorTrap *trap = NULL;
GList *l; GList *l, *error_traps;
int result; int result;
error_traps = g_hash_table_lookup (display_error_traps, xdisplay);
g_return_val_if_fail (error_traps != NULL, Success); g_return_val_if_fail (error_traps != NULL, Success);
/* Find the first trap that hasn't been popped already */ /* Find the first trap that hasn't been popped already */

View File

@ -265,8 +265,6 @@ meta_x11_display_dispose (GObject *object)
x11_display->xroot = None; x11_display->xroot = None;
} }
meta_x11_display_destroy_error_traps (x11_display);
if (x11_display->xdisplay) if (x11_display->xdisplay)
{ {
meta_x11_display_free_events (x11_display); meta_x11_display_free_events (x11_display);
@ -288,6 +286,16 @@ meta_x11_display_dispose (GObject *object)
G_OBJECT_CLASS (meta_x11_display_parent_class)->dispose (object); G_OBJECT_CLASS (meta_x11_display_parent_class)->dispose (object);
} }
static void
meta_x11_display_finalize (GObject *object)
{
MetaX11Display *x11_display = META_X11_DISPLAY (object);
meta_x11_display_destroy_error_traps (x11_display);
G_OBJECT_CLASS (meta_x11_display_parent_class)->finalize (object);
}
static void static void
on_x11_display_opened (MetaX11Display *x11_display, on_x11_display_opened (MetaX11Display *x11_display,
MetaDisplay *display) MetaDisplay *display)
@ -302,6 +310,7 @@ meta_x11_display_class_init (MetaX11DisplayClass *klass)
GObjectClass *object_class = G_OBJECT_CLASS (klass); GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->dispose = meta_x11_display_dispose; object_class->dispose = meta_x11_display_dispose;
object_class->finalize = meta_x11_display_finalize;
} }
static void static void