[plt-scheme] FFI callbacks stored in uncooperatively realloc'd C

From: Chongkai Zhu (czhu at cs.utah.edu)
Date: Wed Nov 25 12:54:29 EST 2009

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
>



Posted on the users mailing list.