Good idea. Turns out that there are already printf's in there, I just need to define debug_free. And doing that . . . it's XFree_Screen().
[ . . . ] release_rc_XColor(0xfd7900) release_rc_XGCValues(0xfd8950) release_rc_XColor(0xfd7640) release_rc_XGCValues(0xfd7790) release_rc_XColor(0xfd53f0) release_rc_XGCValues(0xfd5850) XFree_Screen(0xfc8900) *** glibc detected *** ../../gsi/gsi: munmap_chunk(): invalid pointer: 0x0000000000fc8900 *** ======= Backtrace: ========= /lib/libc.so.6(+0x71ad6)[0x2b7e851c1ad6] /usr/lib/libX11.so.6(XFree+0x9)[0x2b7e85b60ec9] /home/dab/src/gambc-v4_6_0/examples/Xlib-simple/Xlib.o1(XFree_Screen+0x2f)[0x2b7e854d0d4b] ../../gsi/gsi(___release_foreign+0x4d)[0x4c6832] ../../gsi/gsi(___garbage_collect+0x9b0)[0x4c42f9] ../../gsi/gsi[0x4deedd] ../../gsi/gsi(___call+0x104)[0x4c10f3] ../../gsi/gsi(___setup+0xf47)[0x4c20bb] ../../gsi/gsi(___main+0x9c5)[0x4d6eba] ../../gsi/gsi(___main_char+0x66)[0x4cb32d] ../../gsi/gsi(main+0x15)[0x4bf8b5] /lib/libc.so.6(__libc_start_main+0xfd)[0x2b7e8516ec4d] ../../gsi/gsi[0x4bd369] ======= Memory map: ======== [ . . .]
To verify, commenting out the XFree(p) call in XFree_Screen 'fixes' the problem too.
However, while trying this from a different machine this morning I came across a rather strange effect. If I'm running it to a remote X display, it doesn't crash. Only crashes if the bounce program is running on the same machine as my display.
-Dave
On 01/14/2011 05:03 AM, Mikael wrote:
For the list: Can you maybe add a printf("ENTERED release function XYZ for obj %l!\n",[the pointer of the object to be released]); at the beginning and printf("DONE w release function XYZ!\n"); after release was made, to those release functions, that could help us find exactly what didn't work.
Kind regards
Afficher les réponses par date
On 2011-01-14, at 10:01 AM, David Bridgham wrote:
Good idea. Turns out that there are already printf's in there, I just need to define debug_free. And doing that . . . it's XFree_Screen().
[ . . . ] release_rc_XColor(0xfd7900) release_rc_XGCValues(0xfd8950) release_rc_XColor(0xfd7640) release_rc_XGCValues(0xfd7790) release_rc_XColor(0xfd53f0) release_rc_XGCValues(0xfd5850) XFree_Screen(0xfc8900) *** glibc detected *** ../../gsi/gsi: munmap_chunk(): invalid pointer: 0x0000000000fc8900 *** ======= Backtrace: ========= /lib/libc.so.6(+0x71ad6)[0x2b7e851c1ad6] /usr/lib/libX11.so.6(XFree+0x9)[0x2b7e85b60ec9] /home/dab/src/gambc-v4_6_0/examples/Xlib-simple/Xlib.o1(XFree_Screen+0x2f)[0x2b7e854d0d4b] ../../gsi/gsi(___release_foreign+0x4d)[0x4c6832] ../../gsi/gsi(___garbage_collect+0x9b0)[0x4c42f9] ../../gsi/gsi[0x4deedd] ../../gsi/gsi(___call+0x104)[0x4c10f3] ../../gsi/gsi(___setup+0xf47)[0x4c20bb] ../../gsi/gsi(___main+0x9c5)[0x4d6eba] ../../gsi/gsi(___main_char+0x66)[0x4cb32d] ../../gsi/gsi(main+0x15)[0x4bf8b5] /lib/libc.so.6(__libc_start_main+0xfd)[0x2b7e8516ec4d] ../../gsi/gsi[0x4bd369] ======= Memory map: ======== [ . . .]
To verify, commenting out the XFree(p) call in XFree_Screen 'fixes' the problem too.
However, while trying this from a different machine this morning I came across a rather strange effect. If I'm running it to a remote X display, it doesn't crash. Only crashes if the bounce program is running on the same machine as my display
Could it be that your Xlib is returning a pointer to a statically allocated Screen structure? It is hard to tell from the Xlib documentation what is guaranteed to be a freshly allocated structure and what can be statically allocated. Do you know?
Marc
On 01/14/2011 02:53 PM, Marc Feeley wrote:
However, while trying this from a different machine this morning I came across a rather strange effect. If I'm running it to a remote X display, it doesn't crash. Only crashes if the bounce program is running on the same machine as my display
Could it be that your Xlib is returning a pointer to a statically allocated Screen structure? It is hard to tell from the Xlib documentation what is guaranteed to be a freshly allocated structure and what can be statically allocated. Do you know?
Turns out it was not because of running it on a remote machine vs local, but whether I was running it from screen 0 or screen 1. One of the two machines I've been using is dual-headed.
An array of screen structures is allocated and stashed away in the display structure. If I run it on Screen 1, the screen pointer points into the middle of the allocated memory block and XFree crashes. If I run it from screen 0, the screen pointer points to the beginning of the allocated memory and XFree "works", though I suspect it leaves a stale pointer in the display structure.
I think it's safe to not free the screen structure explicitly as it will be free'd later when XCloseDisplay is called which calls _XFreeDisplayStructure. At least that's what I see in the Xlib sources I have.
-Dave
On 2011-01-14, at 4:37 PM, David Bridgham wrote:
On 01/14/2011 02:53 PM, Marc Feeley wrote:
However, while trying this from a different machine this morning I came across a rather strange effect. If I'm running it to a remote X display, it doesn't crash. Only crashes if the bounce program is running on the same machine as my display
Could it be that your Xlib is returning a pointer to a statically allocated Screen structure? It is hard to tell from the Xlib documentation what is guaranteed to be a freshly allocated structure and what can be statically allocated. Do you know?
Turns out it was not because of running it on a remote machine vs local, but whether I was running it from screen 0 or screen 1. One of the two machines I've been using is dual-headed.
An array of screen structures is allocated and stashed away in the display structure. If I run it on Screen 1, the screen pointer points into the middle of the allocated memory block and XFree crashes. If I run it from screen 0, the screen pointer points to the beginning of the allocated memory and XFree "works", though I suspect it leaves a stale pointer in the display structure.
I think it's safe to not free the screen structure explicitly as it will be free'd later when XCloseDisplay is called which calls _XFreeDisplayStructure. At least that's what I see in the Xlib sources I have.
-Dave
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
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
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