From: Tomas Z. <zel...@gm...> - 2005-09-30 06:36:12
|
Thanks, I'll try the patch and report. Looking at it for another time, I should probably try it again without calling (init) - my intention was to create the callback at *init-hooks* time anyway. I am still a bit confused - I thought the call to init before image saving would have no effect when loading image, as clisp has no way of knowing what was saved by another library (readline), and I do not understand why calling the function to get callback at *init-hooks* time should produce invalid reference. As I've said, I'll report about result of patch. BTW, replacing :default with library name string did not help. Thanks, Tomas Zellerin 2005/9/30, Sam Steingold <sd...@gn...>: > > * Tomas Zellerin <mryyreva@tznvy.pbz> [2005-09-29 08:14:30 +0200]: > > > > while trying to make more from included readline, I encountered a > > problem that can be shown on this example: > > > > (use-package 'ffi) > > (def-call-out add-defun > > (:name "rl_add_defun") > > (:library :default) > > (:arguments (name c-string :in :malloc-free) > > (callback (c-function (:language :stdc) > > (:arguments (rep int) (char int))) > > :in :malloc-free) > > (key int)) > > (:language :stdc) > > (:return-type int)) > > (defun init () > > (labels ((edit-history (key rep) > > (print key) > > (print rep))) > > (add-defun "edit-history" #'edit-history -1))) > > (init) > > (push #'init *init-hooks*) > > (saveinitmem "foo") > > > > That is, a function with callback to linux is defined and then called. > > Now, this works fine when loaded (compiled or not), but when later > > loaded from image, it makes problem when compiled: > > > > $ clisp -norc -C problem.lisp > > $ clisp -q -M foo.mem > > > > *** - FFI::FOREIGN-CALL-OUT: #<INVALID FOREIGN-POINTER #x00000000> come= s from > > a previous Lisp session and is invalid > > The following restarts are available: > > SKIP :R1 skip (SAVEINITMEM foo) > > STOP :R2 stop loading file /home/tomas/src/misc/problem.= lisp > > ABORT :R3 ABORT > > $ clisp -norc problem.lisp > > $ clisp -q -M foo.mem > > [1]> > > > > When read-history is defined with defun, it makes same problem even > > when not compiled. > > a callback is allocated on the heap (with malloc) and it cannot be saved > into an image. > the reason you are not getting the error under some conditions is that > there is no attempt made to re-use the saved callback because the lisp > function corresponding to the callback was not found in the callback > hash table. > > PROPOSED SOLUTION: > > 1. exit_ffi() should release all callbacks and replace them in > O(foreign_callin_vector) with NIL. > this is not strictly necessary (you do not have to free all your > mallocs before exit, but I think this is "good taste"). > Bruno, Joerg, should we do this? > > 2. when convert_function_to_foreign() finds in invalid (or NIL) > triple[1], it should just call alloc_callback(); > see the appended patch. > Tomas, could you please try this patch? > it appears to fix the bug you reported. > > -- > Sam Steingold (http://www.podval.org/~sds) running w2k > <http://www.memri.org/> <http://truepeace.org> <http://www.honestreportin= g.com> > <http://www.camera.org> <http://www.savegushkatif.org> <http://pmw.org.il= /> > If abortion is murder, then oral sex is cannibalism. > > > --- foreign.d 21 Sep 2005 14:10:34 -0400 1.144 > +++ foreign.d 29 Sep 2005 18:20:45 -0400 > @@ -442,12 +442,23 @@ > if (equal_fvd(resulttype,Car(acons)) > && equal_argfvds(argtypes,Car(Cdr(acons))) > && eq(flags,Car(Cdr(Cdr(acons))))) { > - var gcv_object_t* triple =3D &TheSvector(TheIarray(O(foreign_c= allin_vector))->data)->data[3*posfixnum_to_V(Cdr(Cdr(Cdr(acons))))-2]; > - triple[2] =3D fixnum_inc(triple[2],1); /* increment reference = count */ > + var uintV f_index =3D posfixnum_to_V(Cdr(Cdr(Cdr(acons)))); > + var gcv_object_t* triple =3D &TheSvector(TheIarray(O(foreign_c= allin_vector))->data)->data[3*f_index-2]; > var object ffun =3D triple[1]; > ASSERT(equal_fvd(resulttype,TheFfunction(ffun)->ff_resulttype))= ; > ASSERT(equal_argfvds(argtypes,TheFfunction(ffun)->ff_argtypes))= ; > ASSERT(eq(flags,TheFfunction(ffun)->ff_flags)); > + var object faddress =3D TheFfunction(ffun)->ff_address; > + if (fp_validp(TheFpointer(TheFaddress(faddress)->fa_base))) { > + triple[2] =3D fixnum_inc(triple[2],1); /* increment referenc= e count */ > + } else { /* callback from the previous session -- renew */ > + /* leave the reference count alone */ > + begin_system_call(); > + TheFaddress(faddress)->fa_offset =3D > + (uintP)alloc_callback(&callback,(void*)(uintP)f_index); > + end_system_call(); > + TheFaddress(faddress)->fa_base =3D O(fp_zero); > + } > return ffun; > } > } > |