From 285b702ef6f73e7eb4ca0da235a287ad1e1f412f Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 15 Jun 2007 20:38:01 +0100 Subject: [PATCH] [cairo-xlib-display] Hide XErrors during processing of the work queue. It is possible for the resources that we defer freeing to be already destroyed and trigger an XError whilst processing the work queue. For example, the application renders to a Window and then destroys the Drawable before proceeding with more rendering. This will trigger an invalid Picture from RenderFreePicture whilst attempting to free the resources. By ignoring the possibility that the application could allocate a fresh resource with the same ID, we can simply hide the XErrors... Fixes: https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=243811 --- src/cairo-xlib-display.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/cairo-xlib-display.c b/src/cairo-xlib-display.c index 5de901110..3ff633e31 100644 --- a/src/cairo-xlib-display.c +++ b/src/cairo-xlib-display.c @@ -405,10 +405,13 @@ void _cairo_xlib_display_notify (cairo_xlib_display_t *display) { cairo_xlib_job_t *jobs, *job, *freelist; + Display *dpy = display->display; CAIRO_MUTEX_LOCK (display->mutex); jobs = display->workqueue; while (jobs != NULL) { + cairo_xlib_error_func_t old_handler; + display->workqueue = NULL; CAIRO_MUTEX_UNLOCK (display->mutex); @@ -422,24 +425,32 @@ _cairo_xlib_display_notify (cairo_xlib_display_t *display) } while (jobs != NULL); freelist = jobs = job; + /* protect the notifies from triggering XErrors + * XXX There is a remote possibility that the application has + * been reallocated an XID that we are about to destroy here... */ + XSync (dpy, False); + old_handler = XSetErrorHandler (_noop_error_handler); + do { job = jobs; jobs = job->next; switch (job->type){ case WORK: - job->func.work.notify (display->display, job->func.work.data); + job->func.work.notify (dpy, job->func.work.data); if (job->func.work.destroy != NULL) job->func.work.destroy (job->func.work.data); break; case RESOURCE: - job->func.resource.notify (display->display, - job->func.resource.xid); + job->func.resource.notify (dpy, job->func.resource.xid); break; } } while (jobs != NULL); + XSync (dpy, False); + XSetErrorHandler (old_handler); + CAIRO_MUTEX_LOCK (display->mutex); do { job = freelist;