followup fix for thread deadlocks (#1193742, fdo#84252)
This commit is contained in:
parent
4b613c90a0
commit
cd4954b149
132
0054-Fix-a-thread-hang-with-xcb_wait_for_special_event.patch
Normal file
132
0054-Fix-a-thread-hang-with-xcb_wait_for_special_event.patch
Normal file
@ -0,0 +1,132 @@
|
||||
From 5b40681c887192307f3ae147d2158870aa79c05f Mon Sep 17 00:00:00 2001
|
||||
From: Uli Schlachter <psychon@znc.in>
|
||||
Date: Fri, 12 Jun 2015 15:13:05 +0200
|
||||
Subject: [PATCH 54/54] Fix a thread hang with xcb_wait_for_special_event()
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Consider the following:
|
||||
|
||||
- Two threads are calling xcb_wait_for_special_event() and xcb_wait_for_reply()
|
||||
concurrently.
|
||||
- The thread doing xcb_wait_for_reply() wins the race and poll()s the socket for
|
||||
readability.
|
||||
- The other thread will be put to sleep on the special_event_cond of the special
|
||||
event (this is done in _xcb_conn_wait() via the argument
|
||||
xcb_wait_for_special_event() gives it).
|
||||
- The first thread gets its reply, but does not yet receive any special event.
|
||||
|
||||
In this case, the first thread will return to its caller. On its way out, it
|
||||
will call _xcb_in_wake_up_next_reader(), but that function cannot wake up
|
||||
anything since so far it did not handle xcb_wait_for_special_event().
|
||||
|
||||
Thus, the first thread stays blocked on the condition variable and no thread
|
||||
tries to read from the socket.
|
||||
|
||||
A test case demonstrating this problem is available at the bug report.
|
||||
|
||||
Fix this similar to how we handle this with xcb_wait_for_reply():
|
||||
|
||||
The function wait_for_reply() adds an entry into a linked list of threads that
|
||||
wait for a reply. Via this list, _xcb_in_wake_up_next_reader() can wake up this
|
||||
thread so that it can call _xcb_conn_wait() again and then poll()s the socket.
|
||||
|
||||
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=84252
|
||||
Signed-off-by: Uli Schlachter <psychon@znc.in>
|
||||
Tested-by: Michel Dänzer <michel.daenzer@amd.com>
|
||||
---
|
||||
src/xcb_in.c | 32 ++++++++++++++++++++++++++++++++
|
||||
src/xcbint.h | 1 +
|
||||
2 files changed, 33 insertions(+)
|
||||
|
||||
diff --git a/src/xcb_in.c b/src/xcb_in.c
|
||||
index 322bed8..bab4bc7 100644
|
||||
--- a/src/xcb_in.c
|
||||
+++ b/src/xcb_in.c
|
||||
@@ -97,6 +97,11 @@ typedef struct reader_list {
|
||||
struct reader_list *next;
|
||||
} reader_list;
|
||||
|
||||
+typedef struct special_list {
|
||||
+ xcb_special_event_t *se;
|
||||
+ struct special_list *next;
|
||||
+} special_list;
|
||||
+
|
||||
static void remove_finished_readers(reader_list **prev_reader, uint64_t completed)
|
||||
{
|
||||
while(*prev_reader && XCB_SEQUENCE_COMPARE((*prev_reader)->request, <=, completed))
|
||||
@@ -475,6 +480,26 @@ static void remove_reader(reader_list **prev_reader, reader_list *reader)
|
||||
}
|
||||
}
|
||||
|
||||
+static void insert_special(special_list **prev_special, special_list *special, xcb_special_event_t *se)
|
||||
+{
|
||||
+ special->se = se;
|
||||
+ special->next = *prev_special;
|
||||
+ *prev_special = special;
|
||||
+}
|
||||
+
|
||||
+static void remove_special(special_list **prev_special, special_list *special)
|
||||
+{
|
||||
+ while(*prev_special)
|
||||
+ {
|
||||
+ if(*prev_special == special)
|
||||
+ {
|
||||
+ *prev_special = (*prev_special)->next;
|
||||
+ break;
|
||||
+ }
|
||||
+ prev_special = &(*prev_special)->next;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static void *wait_for_reply(xcb_connection_t *c, uint64_t request, xcb_generic_error_t **e)
|
||||
{
|
||||
void *ret = 0;
|
||||
@@ -750,17 +775,22 @@ xcb_generic_event_t *xcb_poll_for_special_event(xcb_connection_t *c,
|
||||
xcb_generic_event_t *xcb_wait_for_special_event(xcb_connection_t *c,
|
||||
xcb_special_event_t *se)
|
||||
{
|
||||
+ special_list special;
|
||||
xcb_generic_event_t *event;
|
||||
|
||||
if(c->has_error)
|
||||
return 0;
|
||||
pthread_mutex_lock(&c->iolock);
|
||||
|
||||
+ insert_special(&c->in.special_waiters, &special, se);
|
||||
+
|
||||
/* get_special_event returns 0 on empty list. */
|
||||
while(!(event = get_special_event(c, se)))
|
||||
if(!_xcb_conn_wait(c, &se->special_event_cond, 0, 0))
|
||||
break;
|
||||
|
||||
+ remove_special(&c->in.special_waiters, &special);
|
||||
+
|
||||
_xcb_in_wake_up_next_reader(c);
|
||||
pthread_mutex_unlock(&c->iolock);
|
||||
return event;
|
||||
@@ -889,6 +919,8 @@ void _xcb_in_wake_up_next_reader(xcb_connection_t *c)
|
||||
int pthreadret;
|
||||
if(c->in.readers)
|
||||
pthreadret = pthread_cond_signal(c->in.readers->data);
|
||||
+ else if(c->in.special_waiters)
|
||||
+ pthreadret = pthread_cond_signal(&c->in.special_waiters->se->special_event_cond);
|
||||
else
|
||||
pthreadret = pthread_cond_signal(&c->in.event_cond);
|
||||
assert(pthreadret == 0);
|
||||
diff --git a/src/xcbint.h b/src/xcbint.h
|
||||
index f89deba..acce646 100644
|
||||
--- a/src/xcbint.h
|
||||
+++ b/src/xcbint.h
|
||||
@@ -142,6 +142,7 @@ typedef struct _xcb_in {
|
||||
struct event_list *events;
|
||||
struct event_list **events_tail;
|
||||
struct reader_list *readers;
|
||||
+ struct special_list *special_waiters;
|
||||
|
||||
struct pending_reply *pending_replies;
|
||||
struct pending_reply **pending_replies_tail;
|
||||
--
|
||||
2.4.3
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
Name: libxcb
|
||||
Version: 1.11
|
||||
Release: 7%{?dist}
|
||||
Release: 8%{?dist}
|
||||
Summary: A C binding to the X11 protocol
|
||||
License: MIT
|
||||
URL: http://xcb.freedesktop.org/
|
||||
@ -17,6 +17,7 @@ Source1: pthread-stubs.pc.in
|
||||
|
||||
## upstream patches (post 1.11 tag commits)
|
||||
Patch53: 0053-Call-_xcb_wake_up_next_reader-from-xcb_wait_for_spec.patch
|
||||
Patch54: 0054-Fix-a-thread-hang-with-xcb_wait_for_special_event.patch
|
||||
|
||||
BuildRequires: doxygen
|
||||
BuildRequires: graphviz
|
||||
@ -120,6 +121,9 @@ find $RPM_BUILD_ROOT -name '*.la' -delete
|
||||
%{_pkgdocdir}
|
||||
|
||||
%changelog
|
||||
* Thu Jun 25 2015 Rex Dieter <rdieter@fedoraproject.org> 1.11-8
|
||||
- followup fix for thread deadlocks (#1193742, fdo#84252)
|
||||
|
||||
* Wed Jun 17 2015 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.11-7
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user