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 <jamey@minilop.net> Acked-by: Christoph Pfister <christophpfister@gmail.com>
This commit is contained in:
parent
f6b75d6090
commit
a29fbc2645
|
@ -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
|
||||||
++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
|
||||||
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)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue