Hello,

I encounter the following situation on my system reproduceably when I
run the synergy KVM switching software (server side).

Thread A is stuck in this call path:

XSync()
   _XReply()
        // line 625 ff: wait for event_waiter to process first event
        while(dpy->xcb->event_waiter)
        { /* need braces around ConditionWait */
             ConditionWait(dpy, dpy->xcb->event_notify);
        }

I observe that this thread never leaves this while loop any more.

Thread B executes:

XIfEvent()
   _XReadEvents()

Until the event it's waiting for arrives, XIfEvent() calls
_XReadEvents() in a loop with the display lock held. _XReadEvents() only
releases the lock after setting dpy->xcb->event_waiter. Only after
re-acquiring the lock, it clears event_waiter and sends a broadcast for
the condition variable dpy->xcb->event_notify.

In this situation, thread A is effectively blocked: ConditionWait()
receives the broadcast, but before it can acquire the display lock and
return, _XReadEvents() will have set event_waiter once more, so it needs
to wait again.

This goes on forever unless the event XIfEvent() is waiting for arrives.
In some situations, this seems to take a forever too, I'm not sure why
(maybe we are looking at a deadlock situation here in the sense that the
expected condition can't happen unless thread A gets a chance to run).

I am attaching a tentative patch that I've come up with. Please review
it. The rationale is to yield to a request waiter after grabbing one
event. I am currently testing it on my system (too early to come to a
conclusion though, at least it doesn't seem to have caused a regression
so far).

CC'ing Jamey who seems to be the expert on XCB locking matters.

The thread
https://groups.google.com/forum/#!topic/synergy-users/4O_Xod9HV-A
suggests that other people are seeing the same problem. It also suggests
that this only occurs wiht recent versions of synergy. However, IMO the
above analysis rather indicates a general XCB problem. Please comment.

Regards
Martin

--- libX11-1.6.3/src/xcb_io.c	2015-03-09 23:28:45.000000000 +0100
+++ libX11-1.6.3mw/src/xcb_io.c	2016-07-20 08:59:17.676070822 +0200
@@ -424,12 +424,15 @@
 		response = poll_for_response(dpy);
 		if(response)
 			handle_response(dpy, response, False);
-		else if(dpy->xcb->pending_requests->reply_waiter)
+		else if(!dpy->xcb->pending_requests->reply_waiter)
+			_XIOError(dpy);
+
+		/* If there is a reply waiter, give him a chance to run. */
+
+		if(dpy->xcb->pending_requests && dpy->xcb->pending_requests->reply_waiter)
 		{ /* need braces around ConditionWait */
 			ConditionWait(dpy, dpy->xcb->reply_notify);
 		}
-		else
-			_XIOError(dpy);
 	}
 
 	/* The preceding loop established that there is no
_______________________________________________
xorg-devel@lists.x.org: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: https://lists.x.org/mailman/listinfo/xorg-devel

Reply via email to