[plt-scheme] FFI callbacks stored in uncooperatively realloc'd C
Tim Brown wrote:
> Hello,
>
> I am trying to make FFI calls into a legacy C library. The C library
> makes
> heavy use of callback functions. The callbacks are stored in arrays which
> are, themselves, sized using C's own realloc function. There is nothing
> that I can do to rewrite the C code.
>
> When an array of callbacks is realloc'd, and scheme performs a garbage
> collection, then the next callback invocation (from C) throws a
> Segmentation Fault.
>
> I am using mzscheme (cgc) 4.1 on Solaris 5.10 for i386. However, I would
> expect the SEGV to be thrown, since I'm not making any attempt to
> preserve
> the wrapped callback. Principally because I need help in generating the
> code to do so.
>
> A minimal C library. Don't ask me to change it, as it typifies the
> problem. Built into shard object "tim.so":
>
> /*
> --------------------------------------------------------------------------
> */
>
> typedef int (*int_thunk_type)(void);
>
> int_thunk_type Cb = 0;
> int_thunk_type* p_Cb = 0;
>
> void configure_callback(int_thunk_type cb)
> {
> p_Cb = malloc(sizeof(int_thunk_type));
> *p_Cb = cb;
> }
>
> void call_callback(void)
> {
> int i = 1;
> if(p_Cb && *p_Cb)
> {
> printf("calling: 0x%p\n", *p_Cb);
> printf("*p_Cb returned: %d\n", (*p_Cb)());
> printf("called: 0x%p\n", *p_Cb);
> printf("pre realloc: p_Cb = 0x%p\n", p_Cb);
> p_Cb = realloc(p_Cb, sizeof(int_thunk_type) * 10000*i);
> printf("post realloc: p_Cb = 0x%p\n", p_Cb);
> }
> }
> /*
> --------------------------------------------------------------------------
> */
>
> The naive, broken, scheme that I wish to use:
>
> (require scheme/foreign)
> (unsafe!)
>
> (define int-thunk (_fun -> _int))
> (define lib:tim (ffi-lib "tim.so"))
>
> (define configure-callback
> (get-ffi-obj "configure_callback" lib:tim
> (_fun int-thunk -> _void)))
>
> (define call-callback
> (get-ffi-obj "call_callback" lib:tim
> (_fun -> _void)))
>
> (define (meaning-of-life) 42)
> (configure-callback meaning-of-life)
> (define meaning-of-life #f)
I haven't be able to try the code on my computer yet, but why you
redefine `meaning-of-life' here? According to PLT doc (the #:keep part
of _cprocedure), if you just keep the original `meaning-of-life' in
memory(only remove it when you don't need the C call back anymore)
everything should work.
Chongkai
> (call-callback)
> (collect-garbage)
> (call-callback)
> (collect-garbage)
> (call-callback)
>
>
> Any assistance is gratefully received.
>
> Thanks and regards,
>
> Tim
>