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
|
Name: libxcb
|
||||||
Version: 1.11
|
Version: 1.11
|
||||||
Release: 7%{?dist}
|
Release: 8%{?dist}
|
||||||
Summary: A C binding to the X11 protocol
|
Summary: A C binding to the X11 protocol
|
||||||
License: MIT
|
License: MIT
|
||||||
URL: http://xcb.freedesktop.org/
|
URL: http://xcb.freedesktop.org/
|
||||||
@ -17,6 +17,7 @@ Source1: pthread-stubs.pc.in
|
|||||||
|
|
||||||
## upstream patches (post 1.11 tag commits)
|
## upstream patches (post 1.11 tag commits)
|
||||||
Patch53: 0053-Call-_xcb_wake_up_next_reader-from-xcb_wait_for_spec.patch
|
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: doxygen
|
||||||
BuildRequires: graphviz
|
BuildRequires: graphviz
|
||||||
@ -120,6 +121,9 @@ find $RPM_BUILD_ROOT -name '*.la' -delete
|
|||||||
%{_pkgdocdir}
|
%{_pkgdocdir}
|
||||||
|
|
||||||
%changelog
|
%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
|
* 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
|
- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user