Following debugging of a strange issue where oFono appeared to be sending a D-Bus signal from the wrong object, but I eventually realised that the problem was in my own code...
Neil
>From 02d80ad14c3bb8f89d7ba807dac658be6dd06df1 Mon Sep 17 00:00:00 2001 From: Neil Jerram <n...@ossau.homelinux.net> Date: Mon, 30 Jan 2012 21:12:37 +0000 Subject: [PATCH] Doc: protecting procedure->pointer pointers from GC * doc/ref/api-foreign.texi (Dynamic FFI): New text covering when pointers need to be retained. --- doc/ref/api-foreign.texi | 33 +++++++++++++++++++++++++++++++++ 1 files changed, 33 insertions(+), 0 deletions(-) diff --git a/doc/ref/api-foreign.texi b/doc/ref/api-foreign.texi index 6ece7f8..19d6b29 100644 --- a/doc/ref/api-foreign.texi +++ b/doc/ref/api-foreign.texi @@ -961,6 +961,39 @@ function can be made accessible to Scheme (@pxref{Array Sort Function, And voil@`a! +If you use @code{procedure->pointer} to pass a Scheme procedure as a +callback for a C library to invoke asynchronously later --- for example, +as a handler for a D-Bus signal --- you must somehow keep a reference to +the pointer that @code{procedure->pointer} returns, for as long as the C +library might invoke the callback. Otherwise the pointer can be +prematurely garbage collected, leading to unsafe and arbitrary behaviour +if the now-invalid callback is called. + +This example, which registers a Scheme procedure as a handler for a +GObject signal, uses @code{make-object-property} to do that: + +@example +(define gobject-signal-handlers (make-object-property)) + +(define (gobject-connect object signal proc) + (let ((ptr (procedure->pointer void + (lambda (...C callback args...) + (proc ...Scheme args...)) + (list ...C callback types...)))) + ;; Protect the pointer from being prematurely collected. + (set! (gobject-signal-handlers object) + (acons signal + ptr + (or (gobject-signal-handlers object) '()))) + ;; Register the handler. + (g_signal_connect_data object + (string->pointer signal) + ptr + %null-pointer + %null-pointer + 0))) +@end example + Note that @code{procedure->pointer} is not supported (and not defined) on a few exotic architectures. Thus, user code may need to check @code{(defined? 'procedure->pointer)}. Nevertheless, it is available on -- 1.7.8.3