diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2007-06-15 20:38:01 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2007-06-15 21:16:49 +0100 |
commit | 285b702ef6f73e7eb4ca0da235a287ad1e1f412f (patch) | |
tree | f0b68f3b35fa66f3b9eeb11bbb10f14f8b481ea0 | |
parent | 7016614dd90798247524f0c118f462aa2e7ef673 (diff) |
[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
-rw-r--r-- | src/cairo-xlib-display.c | 17 |
1 files changed, 14 insertions, 3 deletions
diff --git a/src/cairo-xlib-display.c b/src/cairo-xlib-display.c index 5de90111..3ff633e3 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; |