I'm Cc-ing cffi-devel and sbcl-devel, since I'm sure more people will be interested in this and hopefully others will help in figuring this out.
On 2005-dec-31, at 13:59, Thomas F. Burdick wrote:
I noticed in the #lisp logs that you're having problems preserving callbacks across image saves. SBCL already goes to quite a bit of effort to make sure this works. From C's point of view, the callbacks will never move. But because your library is in lisp, and persists across image saves, from its point of view, callback objects can move at arbitrary times. Instead of storing SAPs, you should store the alien-value object that alien-lambda returns. If you actually need the SAP, get it only when you need it, using alien-sap.
We're not even testing if the callback moves or not. Our libtest is not saving the callbacks' address.
Here's the a testcase, using sb-alien (sort of):
luis@nhop:/tmp$ cat sbcl-callback.lisp (use-package :sb-alien)
(define-alien-routine "qsort" void (base system-area-pointer) (nmemb int) (size int) (compar system-area-pointer))
(defparameter *callback* (sb-alien::alien-lambda int ((a system-area-pointer) (b system-area-pointer)) (let ((x (sb-sys:signed-sap-ref-32 a 0)) (y (sb-sys:signed-sap-ref-32 b 0))) (cond ((> x y) 1) ((< x y) -1) (t 0)))))
(defun test () (let ((array (alien-sap (make-alien (unsigned 32) 10)))) (dotimes (i 10) (setf (sb-sys:signed-sap-ref-32 array (* i 4)) (nth i '(7 2 8 9 6 1 10 3 5 4)))) (qsort array 10 4 (alien-sap *callback*)) (dotimes (i 10) (format t "~A " (sb-sys:signed-sap-ref-32 array (* i 4)))) (free-alien (sap-alien array (* (unsigned 32))))))
luis@nhop:/tmp$ sbcl --sysinit /dev/null --userinit /dev/null This is SBCL 0.9.8.3, an implementation of ANSI Common Lisp. More information about SBCL is available at http://www.sbcl.org/.
SBCL is free software, provided as is, with absolutely no warranty. It is mostly in the public domain; some portions are provided under BSD-style licenses. See the CREDITS and COPYING files in the distribution for more information. * (load "sbcl-callback.lisp")
T * (test) 1 2 3 4 5 6 7 8 9 10 NIL * (sb-ext:save-lisp-and-die "test.core") [undoing binding stack and other enclosing state... done] [saving current Lisp image into /tmp/test.core: writing 1584 bytes from the read-only space at 0x01000000 writing 1368 bytes from the static space at 0x05000000 writing 22609920 bytes from the dynamic space at 0x09000000 done] luis@nhop:/tmp$ sbcl --core test.core This is SBCL 0.9.8.3, an implementation of ANSI Common Lisp. More information about SBCL is available at http://www.sbcl.org/.
SBCL is free software, provided as is, with absolutely no warranty. It is mostly in the public domain; some portions are provided under BSD-style licenses. See the CREDITS and COPYING files in the distribution for more information. * (test)
debugger invoked on a SB-KERNEL::MEMORY-FAULT-ERROR: memory fault
Type HELP for debugger help, or (SB-EXT:QUIT) to exit from SBCL.
restarts (invokable by number or by possibly-abbreviated name): 0: [ABORT] Exit debugger, returning to top level.
(SB-KERNEL::MEMORY-FAULT-ERROR) 0]
Any pointers? Well, I'm off to party. Happy new year!