mirror of
https://gitlab.freedesktop.org/xorg/lib/libx11.git
synced 2026-05-05 12:17:59 +02:00
Fix lockup in _XReply() caused by recursive synchronization
This patch is based on a suggestion made by Uli Schlachter in a comment to the bug report https://gitlab.freedesktop.org/xorg/lib/libx11/issues/93. Explanation of the bug (given by Uli Schlachter as well): An error was received and handled. Since there was an error callback set, Xlib unlocks the display, runs the error callback, and then locks the display again. This goes through _XLockDisplay and then calls _XSeqSyncFunction. On this "lock the thing"-path, Xlib notices that sequence numbers are close to wrap-around and tries to send a GetInputFocus request. However, the earlier calls already registered themselves as "we are handling replies/errors, do not interfere!" and so the code here waits for "that other thread" to be done before it continues. Only that there is no other thread, but it is this thread itself and thus a deadlock follows. The bug is relatively easy to reproduce on any desktop environment by using actively a touchscreen input that supports multitouch, i.e. practically all mobile devices are affected. Fixes: https://gitlab.freedesktop.org/xorg/lib/libx11/issues/93 Suggested-by: Uli Schlachter <psychon@znc.in> Tested-by: Dmitry Osipenko <digetx@gmail.com> Reported-by: Dmitry Osipenko <digetx@gmail.com> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
This commit is contained in:
parent
1f1ca0863f
commit
f5ba2c632a
3 changed files with 7 additions and 1 deletions
|
|
@ -202,6 +202,9 @@ struct _XDisplay
|
|||
unsigned long last_request_read_upper32bit;
|
||||
unsigned long request_upper32bit;
|
||||
#endif
|
||||
|
||||
/* avoid recursion on requests sequence number synchronization */
|
||||
Bool req_seq_syncing; /* requests syncing is in-progress */
|
||||
};
|
||||
|
||||
#define XAllocIDs(dpy,ids,n) (*(dpy)->idlist_alloc)(dpy,ids,n)
|
||||
|
|
|
|||
|
|
@ -201,6 +201,7 @@ XOpenDisplay (
|
|||
X_DPY_SET_LAST_REQUEST_READ(dpy, 0);
|
||||
dpy->default_screen = iscreen; /* Value returned by ConnectDisplay */
|
||||
dpy->last_req = (char *)&_dummy_request;
|
||||
dpy->req_seq_syncing = False;
|
||||
|
||||
/* Initialize the display lock */
|
||||
if (InitDisplayLock(dpy) != 0) {
|
||||
|
|
|
|||
|
|
@ -218,10 +218,12 @@ void _XSeqSyncFunction(
|
|||
xGetInputFocusReply rep;
|
||||
_X_UNUSED register xReq *req;
|
||||
|
||||
if ((X_DPY_GET_REQUEST(dpy) - X_DPY_GET_LAST_REQUEST_READ(dpy)) >= (65535 - BUFSIZE/SIZEOF(xReq))) {
|
||||
if ((X_DPY_GET_REQUEST(dpy) - X_DPY_GET_LAST_REQUEST_READ(dpy)) >= (65535 - BUFSIZE/SIZEOF(xReq)) && !dpy->req_seq_syncing) {
|
||||
dpy->req_seq_syncing = True;
|
||||
GetEmptyReq(GetInputFocus, req);
|
||||
(void) _XReply (dpy, (xReply *)&rep, 0, xTrue);
|
||||
sync_while_locked(dpy);
|
||||
dpy->req_seq_syncing = False;
|
||||
} else if (sync_hazard(dpy))
|
||||
_XSetPrivSyncFunction(dpy);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue