[mcclim-devel] [bug] Asynchronous ID-CHOICE-ERROR -- CLX or McCLIM?
Nikodemus Siivola
nikodemus at random-state.net
Fri Aug 22 09:15:58 UTC 2008
On Fri, Aug 22, 2008 at 6:06 AM, Andy Hefner <ahefner at gmail.com> wrote:
> I just encountered the "Asynchronous ID-CHOICE-ERROR" myself tonight,
> in my case when multiple mcclim applications (in multiple threads) on
> one screen race to repaint. I don't know if it's related to Nikodemus'
> test case, which doesn't make any use of threads (excluding the
> omnipresent CLX event dispatching thread), but at least it's the same
> error.
I don't remember offhand for sure, but I think that was actually on a
single-threaded SBCL -- so there would perforce be only one thread in
Lisp Land.
Since it seems to be in danger of falling through the cracks, here is
a (possibly related) report from sbcl-devel.
Cheers,
-- Nikodemus
---------- Forwarded message ----------
From: Shawn <sabetts at gmail.com>
Date: Sat, Jul 12, 2008 at 5:27 AM
Subject: Re: [Sbcl-devel] breaking the clx xid cache
To: sbcl-devel at lists.sf.net
Hi folks,
It looks like the portable-clx mailing list is down so I'm sending this here.
In stumpwm I've been getting more and more error reports where the
:window slot for events is a pixmap instead of a window. I've tracked
it to a problem with the xid cache in clx. X appears to be recycling
XIDs which confuses clx. Here's a function that exposes the bug:
(defun break-display-xid-cache ()
(labels ((make-win (dpy)
(xlib:create-window :parent (xlib:screen-root (first
(xlib:display-roots dpy))) :x 0 :y 0 :width 50 :height 50))
(make-pixmap (window)
(xlib:create-pixmap :width (random 100) :height (random
100) :depth 8 :drawable window))
(first-pass (dpy)
;; Open a fresh connection. Create a window and a pixmap.
(let* ((dpy2 (xlib:open-default-display))
(window (make-win dpy2))
(pixmap (make-pixmap window)))
;; make the pixmap the window's icon pixmap hint.
(setf (xlib:wm-hints window) (xlib:make-wm-hints
:icon-pixmap pixmap))
(format t "Window ID: ~s pixmap ID: ~s~%"
(xlib:window-id window) (xlib:pixmap-id pixmap))
(xlib:display-finish-output dpy2)
;; On the old connection, list the root window children
;; and the icon pixmap hint to cache their XIDs.
(loop for w in (xlib:query-tree (xlib:screen-root (first
(xlib:display-roots dpy))))
for hints = (xlib:wm-hints w)
when hints
do (format t "top level window id: ~s | icon pixmap
hint: ~s~%" (xlib:window-id w) (xlib:wm-hints-icon-pixmap hints)))
(xlib:close-display dpy2)))
(second-pass (dpy)
;; Open a fresh connection and create 2 windows.
(let* ((dpy2 (xlib:open-default-display))
(window1 (make-win dpy2))
(window2 (make-win dpy2)))
(format t "Window#1 ID: ~s Window#2 ID: ~s~%"
(xlib:window-id window1) (xlib:window-id window2))
(xlib:display-finish-output dpy2)
;; On the old connection, list the root window children
;; and note the second window is erroneously a pixmap
;; due to too agressive caching in clx.
(loop for w in (xlib:query-tree (xlib:screen-root (first
(xlib:display-roots dpy))))
do (format t "window: ~s~%" w))
(xlib:close-display dpy2))))
(let ((dpy (xlib:open-default-display)))
(first-pass dpy)
(second-pass dpy)
(xlib:close-display dpy))))
Note that the last window in the window list printed at the end is a
pixmap and not a window! Here's the relevant output when i run it:
* (break-display-xid-cache)
Window ID: 14680065 pixmap ID: 14680066
top level window id: 14680065 | icon pixmap hint: #<XLIB:PIXMAP :0 E00002>
Window#1 ID: 14680065 Window#2 ID: 14680066
window: #<XLIB:WINDOW :0 E00001>
window: #<XLIB:PIXMAP :0 E00002>
NIL
*
I propose the following patch. Since a cache error isn't the sign of a
bug, I don't think checking the type should depend +type-check?+
constant. In the event of a lookup error, I've added two restarts for
invalidating the cache and creating fresh XID cache entries. This is
how it has been addressed in new-clx.
--- display.lisp 2005-08-26 03:13:28.000000000 -0700
+++ display.lisp 2008-07-11 17:22:39.000000000 -0700
@@ -199,17 +199,21 @@
:display display :id id))
(save-id display id ,type))
;; Found. Check the type
- ,(cond ((null +type-check?+)
- `(t ,type))
- ((member type '(window pixmap))
- `((type? ,type
'drawable) ,type))
- (t `((type? ,type
',type) ,type)))
- ,@(when +type-check?+
- `((t (x-error 'lookup-error
- :id id
- :display display
- :type ',type
- :object ,type))))))
+ ((type? ,type ',type) ,type)
+ (t
+ (restart-case
+ (x-error 'lookup-error
+ :id id
+ :display display
+ :type ',type
+ :object ,type)
+ (one ()
+ :report "Invalidate this
cache entry"
+ (save-id display id
(,(xintern 'make- type) :display display :id id)))
+ (all ()
+ :report "Invalidate all
display cache"
+ (clrhash
(display-resource-id-map display))
+ (save-id display id
(,(xintern 'make- type) :display display :id id)))))))
;; Not being cached. Create a new one each time.
`(,(xintern 'make- type)
:display display :id id))))
-Shawn
More information about the mcclim-devel
mailing list