| Message ID | 1330769283-32223-1-git-send-email-keithp@keithp.com |
|---|---|
| State | Superseded |
| Headers | show |
diff --git a/src/XlibInt.c b/src/XlibInt.c index a8f5d08..12b816f 100644 --- a/src/XlibInt.c +++ b/src/XlibInt.c @@ -214,7 +214,7 @@ void sync_while_locked(Display *dpy) #endif UnlockDisplay(dpy); SyncHandle(); - InternalLockDisplay(dpy, /* don't skip user locks */ 0); + InternalLockDisplay(dpy, /* skip user locks */ 1); #ifdef XTHREADS if (dpy->lock) (*dpy->lock->user_unlock_display)(dpy);
<#part sign=pgpmime> On Sat, 3 Mar 2012 02:08:03 -0800, Keith Packard <keithp@keithp.com> wrote: > sync_while_locked grabs the user lock before performing the sync > operation. Telling InternalLockDisplay to wait for the user lock will > thus deadlock, so don't do that. I've managed to create a short test case for this problem. It uses two threads, one allocating IDs and the other calling XPending. Both threads run as fast as possible, each checking to make sure the other one is still running and aborting when one gets stuck. After a few seconds of run time, the thread calling XPending gets stuck. /* * Test Xlib sync_while_locked bug * * * Compile with: cc -o lockcheck -g lockcheck.c `pkg-config --cflags --libs x11` -lpthread */ #include <pthread.h> #include <X11/Xlib.h> #include <stdio.h> #include <time.h> #include <stdlib.h> Display *dpy; pthread_mutex_t fastmutex = PTHREAD_MUTEX_INITIALIZER; time_t pending_time; time_t alloc_time; void check(void) { time_t now = time(NULL); pthread_mutex_lock(&fastmutex); if ((long) (now - pending_time) > 10) { printf ("pending thread stuck\n"); abort(); } if ((long) (now - alloc_time) > 10) { printf ("alloc thread stuck\n"); abort(); } pthread_mutex_unlock(&fastmutex); } static void * run_pending (void *closure) { int i; for (;;) { pending_time = time(NULL); XPending(dpy); check(); } } static void * run_alloc (void *closure) { for (;;) { alloc_time = time(NULL); XFreeGC(dpy, XCreateGC(dpy, RootWindow(dpy, 0), 0, NULL)); check(); } } main () { pthread_t other_thread; XInitThreads(); dpy = XOpenDisplay(NULL); pthread_create (&other_thread, 0, run_pending, 0); run_alloc(0); }
sync_while_locked grabs the user lock before performing the sync operation. Telling InternalLockDisplay to wait for the user lock will thus deadlock, so don't do that. Signed-off-by: Keith Packard <keithp@keithp.com> --- I don't know how this could ever have failed to deadlock -- sync_while_locked has called _XUserLockDisplay, and so locking_level is non-zero. When _XInternalLockDisplay finds locking_level > 0, it then calls _XDisplayLockWait, which is going to hang around for a *very long time* as the lock is held by the current thread. This patch fixes my application nicely, but I'd love to have someone sanity check this... src/XlibInt.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)