From fcdaaf241ea1511d3ff3879b8ed1ae0a62887861 Mon Sep 17 00:00:00 2001 From: Po Lu Date: Sun, 3 Jul 2022 14:33:02 +0800 Subject: [PATCH] Fix deadlocks with very old versions of libXi * src/xfns.c (setup_xi_event_mask, Fx_create_frame): Set `xi_mask' ourselves if the version of libXi is too old to have working XIGetSelectedEvents. * src/xterm.c (x_destroy_window): Free `xi_mask' with xfree in that case. --- src/xfns.c | 27 ++++++++++++++++++++++++++- src/xterm.c | 7 +++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/xfns.c b/src/xfns.c index ea2b1c0b3d3..331f22763ee 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -3712,6 +3712,16 @@ setup_xi_event_mask (struct frame *f) XIEventMask mask; ptrdiff_t l = XIMaskLen (XI_LASTEVENT); unsigned char *m; +#ifndef HAVE_XINPUT2_1 + /* Set up fallback values, since XIGetSelectedEvents doesn't work + with this version of libXi. */ + XIEventMask *selected; + + selected = xzalloc (sizeof *selected + l); + selected->mask = ((unsigned char *) selected) + sizeof *selected; + selected->mask_len = l; + selected->deviceid = XIAllMasterDevices; +#endif mask.mask = m = alloca (l); memset (m, 0, l); @@ -3736,6 +3746,12 @@ setup_xi_event_mask (struct frame *f) FRAME_X_WINDOW (f), &mask, 1); + /* Fortunately `xi_masks' isn't used on GTK 3, where we really have + to get the event mask from the X server. */ +#ifndef HAVE_XINPUT2_1 + memcpy (selected->mask, m, l); +#endif + memset (m, 0, l); #endif /* !HAVE_GTK3 */ @@ -3775,6 +3791,12 @@ setup_xi_event_mask (struct frame *f) XISelectEvents (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &mask, 1); + +#ifndef HAVE_XINPUT2_1 + FRAME_X_OUTPUT (f)->xi_masks = selected; + FRAME_X_OUTPUT (f)->num_xi_masks = 1; +#endif + unblock_input (); } #endif @@ -4935,7 +4957,10 @@ This function is an internal primitive--use `make-frame' instead. */) x_icon (f, parms); x_make_gc (f); -#ifdef HAVE_XINPUT2 + /* While this function is present in versions of libXi that only + support 2.0, it does not release the display lock after + finishing, leading to a deadlock. */ +#if defined HAVE_XINPUT2 && defined HAVE_XINPUT2_1 if (dpyinfo->supports_xi2) FRAME_X_OUTPUT (f)->xi_masks = XIGetSelectedEvents (dpyinfo->display, FRAME_X_WINDOW (f), diff --git a/src/xterm.c b/src/xterm.c index 4353b173cab..0aca949dbc7 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -25728,8 +25728,15 @@ x_destroy_window (struct frame *f) #endif #ifdef HAVE_XINPUT2 +#ifdef HAVE_XINPUT2_1 if (f->output_data.x->xi_masks) XFree (f->output_data.x->xi_masks); +#else + /* This is allocated by us under very old versions of libXi; see + `setup_xi_event_mask'. */ + if (f->output_data.x->xi_masks) + xfree (f->output_data.x->xi_masks); +#endif #endif xfree (f->output_data.x); -- 2.39.2