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;
/* number of times we've pushed the error handler */
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
* xlib to do it since a) its already cached there b) XQueryExtension
@ -84,6 +85,9 @@ display_error_event (Display *xdisplay,
{
GList *l;
gboolean ignore = FALSE;
GList *error_traps;
error_traps = g_hash_table_lookup (display_error_traps, xdisplay);
for (l = error_traps; l; l = l->next)
{
@ -172,11 +176,12 @@ error_handler_pop (void)
static void
delete_outdated_error_traps (Display *xdisplay)
{
GList *l;
GList *l, *error_traps;
unsigned long processed_sequence;
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)
{
@ -196,6 +201,14 @@ delete_outdated_error_traps (Display *xdisplay)
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);
}
/**
@ -203,8 +216,15 @@ delete_outdated_error_traps (Display *xdisplay)
*/
void
mtk_x11_errors_init (void)
{
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,9 +233,15 @@ mtk_x11_errors_init (void)
void
mtk_x11_errors_deinit (void)
{
g_clear_list (&error_traps, g_free);
init_count--;
g_assert (init_count >= 0);
if (init_count == 0)
{
g_clear_pointer (&display_error_traps, g_hash_table_unref);
XSetErrorHandler (NULL);
}
}
/**
* mtk_x11_error_trap_push: (skip):
@ -224,6 +250,7 @@ void
mtk_x11_error_trap_push (Display *xdisplay)
{
MtkErrorTrap *trap;
GList *error_traps;
delete_outdated_error_traps (xdisplay);
@ -234,7 +261,10 @@ mtk_x11_error_trap_push (Display *xdisplay)
trap->start_sequence = XNextRequest (xdisplay);
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);
g_hash_table_insert (display_error_traps, xdisplay, error_traps);
}
static int
@ -242,9 +272,11 @@ mtk_x11_error_trap_pop_internal (Display *xdisplay,
gboolean need_code)
{
MtkErrorTrap *trap = NULL;
GList *l;
GList *l, *error_traps;
int result;
error_traps = g_hash_table_lookup (display_error_traps, xdisplay);
g_return_val_if_fail (error_traps != NULL, Success);
/* 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;
}
meta_x11_display_destroy_error_traps (x11_display);
if (x11_display->xdisplay)
{
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);
}
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
on_x11_display_opened (MetaX11Display *x11_display,
MetaDisplay *display)
@ -302,6 +310,7 @@ meta_x11_display_class_init (MetaX11DisplayClass *klass)
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->dispose = meta_x11_display_dispose;
object_class->finalize = meta_x11_display_finalize;
}
static void