Commit a29fbc26 authored by Jamey Sharp's avatar Jamey Sharp
Browse files

Don't hold the xlib-xcb lock while sleeping: that allows deadlock.



With this patch, `ico -threads 2` runs without deadlock.

Many thanks to Christoph Pfister <christophpfister@gmail.com> for
pointing out the problem, providing detailed analyses, explaining it to
me repeatedly until I understood what was going on, and proposing and
reviewing possible solutions.

Signed-off-by: Jamey Sharp's avatarJamey Sharp <jamey@minilop.net>
Acked-by: default avatarChristoph Pfister <christophpfister@gmail.com>
parent f6b75d60
...@@ -290,12 +290,25 @@ void _xcb_unlock_io(xcb_connection_t *c) ...@@ -290,12 +290,25 @@ void _xcb_unlock_io(xcb_connection_t *c)
void _xcb_wait_io(xcb_connection_t *c, pthread_cond_t *cond) void _xcb_wait_io(xcb_connection_t *c, pthread_cond_t *cond)
{ {
int xlib_locked = c->xlib.lock;
if(xlib_locked)
{
c->xlib.lock = 0;
pthread_cond_broadcast(&c->xlib.cond);
}
pthread_cond_wait(cond, &c->iolock); pthread_cond_wait(cond, &c->iolock);
if(xlib_locked)
{
while(c->xlib.lock)
pthread_cond_wait(&c->xlib.cond, &c->iolock);
c->xlib.lock = 1;
c->xlib.thread = pthread_self();
}
} }
int _xcb_conn_wait(xcb_connection_t *c, pthread_cond_t *cond, struct iovec **vector, int *count) int _xcb_conn_wait(xcb_connection_t *c, pthread_cond_t *cond, struct iovec **vector, int *count)
{ {
int ret; int ret, xlib_locked;
fd_set rfds, wfds; fd_set rfds, wfds;
/* If the thing I should be doing is already being done, wait for it. */ /* If the thing I should be doing is already being done, wait for it. */
...@@ -316,6 +329,12 @@ int _xcb_conn_wait(xcb_connection_t *c, pthread_cond_t *cond, struct iovec **vec ...@@ -316,6 +329,12 @@ int _xcb_conn_wait(xcb_connection_t *c, pthread_cond_t *cond, struct iovec **vec
++c->out.writing; ++c->out.writing;
} }
xlib_locked = c->xlib.lock;
if(xlib_locked)
{
c->xlib.lock = 0;
pthread_cond_broadcast(&c->xlib.cond);
}
_xcb_unlock_io(c); _xcb_unlock_io(c);
do { do {
ret = select(c->fd + 1, &rfds, &wfds, 0, 0); ret = select(c->fd + 1, &rfds, &wfds, 0, 0);
...@@ -326,6 +345,11 @@ int _xcb_conn_wait(xcb_connection_t *c, pthread_cond_t *cond, struct iovec **vec ...@@ -326,6 +345,11 @@ int _xcb_conn_wait(xcb_connection_t *c, pthread_cond_t *cond, struct iovec **vec
ret = 0; ret = 0;
} }
_xcb_lock_io(c); _xcb_lock_io(c);
if(xlib_locked)
{
c->xlib.lock = 1;
c->xlib.thread = pthread_self();
}
if(ret) if(ret)
{ {
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment