summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2007-06-15 20:38:01 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2007-06-15 21:16:49 +0100
commit285b702ef6f73e7eb4ca0da235a287ad1e1f412f (patch)
treef0b68f3b35fa66f3b9eeb11bbb10f14f8b481ea0
parent7016614dd90798247524f0c118f462aa2e7ef673 (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.c17
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;