https://gitlab.freedesktop.org/xorg/lib/libx11/-/commit/a9e845809bcaae22496bc8aa3ca252b410d5f39b https://bugs.gentoo.org/862115 From a9e845809bcaae22496bc8aa3ca252b410d5f39b Mon Sep 17 00:00:00 2001 From: Matthieu Herrb Date: Fri, 11 Nov 2022 18:55:23 +0100 Subject: [PATCH] Fix 797755 Allow X*IfEvent() to reenter libX11 - the activation logic is reversed - there is also _XInternalLockDisplay() that needs protection - I've found cases (in fvwm2) where the callback calls XCheckIfEvent() recursively. So the flag needs to be a counter. Reviewed-by: Adam Jackson --- a/include/X11/Xlibint.h +++ b/include/X11/Xlibint.h @@ -207,7 +207,7 @@ struct _XDisplay XIOErrorExitHandler exit_handler; void *exit_handler_data; - Bool in_ifevent; + CARD32 in_ifevent; }; #define XAllocIDs(dpy,ids,n) (*(dpy)->idlist_alloc)(dpy,ids,n) --- a/src/ChkIfEv.c +++ b/src/ChkIfEv.c @@ -49,8 +49,8 @@ Bool XCheckIfEvent ( unsigned long qe_serial = 0; int n; /* time through count */ + dpy->in_ifevent++; LockDisplay(dpy); - dpy->in_ifevent = True; prev = NULL; for (n = 3; --n >= 0;) { for (qelt = prev ? prev->next : dpy->head; @@ -80,7 +80,7 @@ Bool XCheckIfEvent ( /* another thread has snatched this event */ prev = NULL; } - dpy->in_ifevent = False; + dpy->in_ifevent--; UnlockDisplay(dpy); return False; } --- a/src/IfEvent.c +++ b/src/IfEvent.c @@ -48,8 +48,8 @@ XIfEvent ( register _XQEvent *qelt, *prev; unsigned long qe_serial = 0; + dpy->in_ifevent++; LockDisplay(dpy); - dpy->in_ifevent = True; prev = NULL; while (1) { for (qelt = prev ? prev->next : dpy->head; @@ -60,7 +60,7 @@ XIfEvent ( *event = qelt->event; _XDeq(dpy, prev, qelt); _XStoreEventCookie(dpy, event); - dpy->in_ifevent = False; + dpy->in_ifevent--; UnlockDisplay(dpy); return 0; } --- a/src/OpenDis.c +++ b/src/OpenDis.c @@ -189,7 +189,7 @@ XOpenDisplay ( dpy->xcmisc_opcode = 0; dpy->xkb_info = NULL; dpy->exit_handler_data = NULL; - dpy->in_ifevent = False; + dpy->in_ifevent = 0; /* * Setup other information in this display structure. --- a/src/PeekIfEv.c +++ b/src/PeekIfEv.c @@ -49,8 +49,8 @@ XPeekIfEvent ( register _XQEvent *prev, *qelt; unsigned long qe_serial = 0; + dpy->in_ifevent++; LockDisplay(dpy); - dpy->in_ifevent = True; prev = NULL; while (1) { for (qelt = prev ? prev->next : dpy->head; @@ -64,7 +64,7 @@ XPeekIfEvent ( _XStoreEventCookie(dpy, ©); *event = copy; } - dpy->in_ifevent = False; + dpy->in_ifevent--; UnlockDisplay(dpy); return 0; } --- a/src/locking.c +++ b/src/locking.c @@ -465,17 +465,33 @@ static void _XIfEventLockDisplay( /* assert(dpy->in_ifevent); */ } +static void _XInternalLockDisplay( + Display *dpy, + Bool wskip + XTHREADS_FILE_LINE_ARGS + ); + +static void _XIfEventInternalLockDisplay( + Display *dpy, + Bool wskip + XTHREADS_FILE_LINE_ARGS + ) +{ + /* assert(dpy->in_ifevent); */ +} + static void _XIfEventUnlockDisplay( Display *dpy XTHREADS_FILE_LINE_ARGS ) { - if (dpy->in_ifevent) + if (dpy->in_ifevent == 0) { + dpy->lock_fns->lock_display = _XLockDisplay; + dpy->lock_fns->unlock_display = _XUnlockDisplay; + dpy->lock->internal_lock_display = _XInternalLockDisplay; + UnlockDisplay(dpy); + } else return; - - dpy->lock_fns->lock_display = _XLockDisplay; - dpy->lock_fns->unlock_display = _XUnlockDisplay; - UnlockDisplay(dpy); } static void _XLockDisplay( @@ -507,6 +523,7 @@ static void _XLockDisplay( if (dpy->in_ifevent) { dpy->lock_fns->lock_display = _XIfEventLockDisplay; dpy->lock_fns->unlock_display = _XIfEventUnlockDisplay; + dpy->lock->internal_lock_display = _XIfEventInternalLockDisplay; } } GitLab