I've pushed some changes to Xlib.scm to remove some of the issues. There is no longer an automatic reclaiming of Display and Screen structures (it is up to the programmer to do the appropriate "free" at the right time). I have also done this for Fonts. Please take a look.
My limited tests indicate that there are no leaks anymore (in the bounce.scm program).
Marc
On 2011-01-15, at 3:11 PM, David Bridgham wrote:
On 01/14/2011 09:30 PM, Marc Feeley wrote:
That's a great analysis! It means that XScreenOfDisplay does not return a pointer to a fresh Screen. It is a pointer to a shared structure, whose deallocation is the responsibility of Xlib. In other words, Xlib.scm should not say:
(define XScreenOfDisplay (c-lambda (Display* ;; display int) ;; screen_number Screen*/XFree "XScreenOfDisplay"))
it should say:
(define XScreenOfDisplay (c-lambda (Display* ;; display int) ;; screen_number Screen* "XScreenOfDisplay"))
That way the pointer to the Screen returned by XScreenOfDisplay will not be managed by the Gambit garbage collector (when the Scheme world drops the pointer to the Screen, it must not be passed to XFree).
Marc
That all looks correct but I'm afraid it's incomplete.
I'd say that Displays should also not be free'd by XFree but rather as a side-effect of XCloseDisplay. I don't think there's any issue with just changing the cleanup routine for Display pointers to be XCloseDisplay. so far but now we have the possibility that some bit of code holds a Screen pointer after XCloseDisplay is called. The Xlib documentation seems to suggest that you just shouldn't use those pointers after they've been freed. That's an okay answer for C maybe, but it seems very un-Schemely. A first step would be to just remove XCloseDisplay from use from the Scheme world.
XCloseDisplay is still called by the garbage collector though, so you could still get into the problem that all Display pointers are dropped but not Screen pointers which now reference free'd memory. One way to deal with this might be to have XScreenOfDisplay return (cons screen display) so any retained Screen pointers reference the Display structure and prevent its garbage collection. Of course all routines that take a Screen* as an argument would have to be fixed to match.
(define XScreenOfDisplay (display screen-number) (cons ((c-lambda (Display* ;; display int) ;; screen_number Screen*/XFree "XScreenOfDisplay") display screen-number) display))
Or maybe there's a better way to handle this within the Gambit FFI system; this is all pretty new to me as you can probably tell.
-Dave