[PATCH] Cannot wait for user lock in sync_while_locked

Keith Packard keithp at keithp.com
Sat Mar 3 23:44:27 PST 2012


<#part sign=pgpmime>
On Sat,  3 Mar 2012 02:08:03 -0800, Keith Packard <keithp at 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);
}

-- 
keith.packard at intel.com


More information about the xorg-devel mailing list