fvwm2/threadlocking.patch

106 lines
3.2 KiB
Diff
Raw Normal View History

From 58cc099368de9b0dd8bf5d2daa0f31d5c373f812 Mon Sep 17 00:00:00 2001
From: Thomas Adam <thomas@xteddy.org>
Date: Tue, 2 May 2023 16:53:10 +0100
Subject: [PATCH] debian bug 1034054: backport fvwm3 xthreadlock()
Backport this fix from fvwm3 to fvwm2:
https://github.com/fvwmorg/fvwm3/commit/5c17c83df4605d2d97999740cf180af983298896
XCheckIfEvent() holds the X display lock and the predicate
function it calls is not allowed to call any Xlib function that
would re-enter the lock.
libX11 1.8.1 enables X display locks unconditionnaly (it was only
enabled by XInitThreads() when called explicitely before) and
thus exposes the issue.
So don't process events in the FCheckPeekIfEvent() predicate, but
instead use a separate handler that is called for the returned event
out of the lock.
---
fvwm/events.c | 9 ++++++++-
libs/FEvent.c | 22 ++++++++++++++++++++++
libs/FEvent.h | 8 ++++++++
3 files changed, 38 insertions(+), 1 deletion(-)
diff --git a/fvwm/events.c b/fvwm/events.c
index a2d024068..7a3d06c3b 100644
--- fvwm/events.c
+++ fvwm/events.c
@@ -258,6 +258,12 @@ static int _pred_weed_accumulate_expose(
return 1;
}
+static int _pred_weed_is_expose(
+ Display *display, XEvent *event, XPointer arg)
+{
+ return (event->type == Expose);
+}
+
static int _pred_weed_handle_expose(
Display *display, XEvent *event, XPointer arg)
{
@@ -4542,7 +4548,8 @@ void handle_all_expose(void)
saved_event = fev_save_event();
FPending(dpy);
- FWeedIfEvents(dpy, _pred_weed_handle_expose, NULL);
+ FWeedAndHandleIfEvents(dpy, _pred_weed_is_expose,
+ _pred_weed_handle_expose, NULL);
fev_restore_event(saved_event);
return;
diff --git a/libs/FEvent.c b/libs/FEvent.c
index 24d019dd1..ec31728a9 100644
--- libs/FEvent.c
+++ libs/FEvent.c
@@ -532,6 +532,28 @@ int FWeedIfEvents(
return weed_args.count;
}
+int FWeedAndHandleIfEvents(
+ Display *display,
+ int (*weed_predicate) (Display *display, XEvent *event, XPointer arg),
+ int (*handler) (Display *display, XEvent *event, XPointer arg),
+ XPointer arg)
+{
+ _fev_weed_args weed_args;
+ XEvent e;
+
+ assert(fev_is_invalid_event_type_set);
+ memset(&weed_args, 0, sizeof(weed_args));
+ weed_args.weed_predicate = weed_predicate;
+ weed_args.arg = arg;
+ if (FCheckPeekIfEvent(display, &e, _fev_pred_weed_if,
+ (XPointer)&weed_args)) {
+ handler(display, &e, arg);
+ }
+ _fev_pred_weed_if_finish(&weed_args);
+
+ return weed_args.count;
+}
+
int FWeedIfWindowEvents(
Display *display, Window window,
int (*weed_predicate) (
diff --git a/libs/FEvent.h b/libs/FEvent.h
index 821aef51a..2622f4474 100644
--- libs/FEvent.h
+++ libs/FEvent.h
@@ -113,6 +113,14 @@ int FWeedIfEvents(
Display *display, XEvent *current_event, XPointer arg),
XPointer arg);
+/* Same as FWeedIfEvents but with a second callback out of XLockDisplay()
+ * to handle events in a lock-safe manner */
+int FWeedAndHandleIfEvents(
+ Display *display,
+ int (*weed_predicate) (Display *display, XEvent *event, XPointer arg),
+ int (*handler) (Display *display, XEvent *event, XPointer arg),
+ XPointer arg);
+
/* Same as FWeedIfEvents but weeds only events for the given window. The
* weed_predicate is only called for events with a matching window. */
int FWeedIfWindowEvents(