summaryrefslogtreecommitdiff
blob: 6021ca25a48de29163704d649f96e266836fbed3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
From a51b7f58173d47b650d77b46c95f4afca138206f Mon Sep 17 00:00:00 2001
From: Chris Wilson <chris@chris-wilson.co.uk>
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 resource that we defer freeing are 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...
---
 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 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_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;
-- 
1.4.4.2