[cairo-commit] 2 commits - src/cairo-xlib-display.c src/cairo-xlib-surface.c

Chris Wilson ickle at kemper.freedesktop.org
Fri Jun 15 13:22:46 PDT 2007


 src/cairo-xlib-display.c |   17 ++++++++++++++---
 src/cairo-xlib-surface.c |    2 ++
 2 files changed, 16 insertions(+), 3 deletions(-)

New commits:
diff-tree 285b702ef6f73e7eb4ca0da235a287ad1e1f412f (from 7016614dd90798247524f0c118f462aa2e7ef673)
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Jun 15 20:38:01 2007 +0100

    [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

diff --git a/src/cairo-xlib-display.c b/src/cairo-xlib-display.c
index 5de9011..3ff633e 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_d
 	} 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;
diff-tree 7016614dd90798247524f0c118f462aa2e7ef673 (from 0c5d28a4e5ce5e4dd72c0f416ce5e960e92b808b)
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Jun 15 20:45:53 2007 +0100

    [cairo-xlib-surface] Check for errors before installing a NOOP error handler.
    
    Call XSync before ignoring errors from XGetImage to avoid hiding
    unassociated errors. Similarly, call XSync before reinstalling the old
    error handler to ensure no errors creep out of the ignored section.

diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index cbd75ad..90333a8 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -542,6 +542,7 @@ _get_image_surface (cairo_xlib_surface_t
     {
 	cairo_xlib_error_func_t old_handler;
 
+	XSync (surface->dpy, False);
 	old_handler = XSetErrorHandler (_noop_error_handler);
 
 	ximage = XGetImage (surface->dpy,
@@ -550,6 +551,7 @@ _get_image_surface (cairo_xlib_surface_t
 			    x2 - x1, y2 - y1,
 			    AllPlanes, ZPixmap);
 
+	XSync (surface->dpy, False);
 	XSetErrorHandler (old_handler);
 
 	/* If we get an error, the surface must have been a window,


More information about the cairo-commit mailing list