caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* [Caml-list] The OCaml garbage collector, finalisers, and the right way of disposing native pointers in C bindings
@ 2016-01-12  9:12 Neuhaeusser, Martin
  2016-01-12  9:37 ` Kim Nguyễn
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Neuhaeusser, Martin @ 2016-01-12  9:12 UTC (permalink / raw)
  To: caml-list

Dear all,

during our work on some SMT solver bindings, a couple of question came up regarding the behavior of the OCaml garbage collector (see also https://github.com/Z3Prover/z3/issues/411). Assume we have defined a record type containing a native pointer to some object from an external C-DLL:

type ocaml_record = {
  native_ptr np;
  [... some more fields ...]
}

When creating an ocaml_record, we register a finalizer that makes the C library dispose the data belonging to the native pointer once the GC collects the OCaml record value:

let f ocaml_record = NativeLib.dispose ocaml_record.np

let create [...] =
  let new_ocaml_record = { ... } in
  Gc.finalise f new_ocaml_record;
  new_ocaml_record

When calling one of the C-stubs, we pass the native pointer from the OCaml record value:

let get_native_pointer ocaml_record = ocaml_record.np

NativeLib.native_function (get_native_pointer ocaml_record)

However, this has the problem that if ocaml_record has become otherwise unreachable, the GC might collect ocaml_record directly after evaluating (get_native_pointer ocaml_record), triggering the finalizer which disposes the data pointed at by ocaml_record.native_ptr. The successive call to NativeLib.native_function (i.e. the C-stub) results in a segfault, as it tries to access data that has previously been freed by the finalizer.

I assume this is a common problem in writing interfaces to C libraries. If so, is there a preferred way how to tackle it?
Two approaches that came to my mind are

1. One could design the C-stubs such that they accept values of type ocaml_record and extract the native pointer within the C stub. In the C-stubs, the GC must not collect an item that has been "pinned" by the CAMLparamX macros, right?
2. One could invent some function that takes an ocaml_record, but does nothing with it and whose calls do not get optimized away by the compiler... Evaluating such a function after the call to NativeLib.native_function would prevent the GC from collecting ocaml_record. However, this feels like a very ugly hack. 

Are there any better ideas? Any help and suggestions are highly appreciated.

Best,
Martin

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2016-01-12 13:06 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-01-12  9:12 [Caml-list] The OCaml garbage collector, finalisers, and the right way of disposing native pointers in C bindings Neuhaeusser, Martin
2016-01-12  9:37 ` Kim Nguyễn
2016-01-12 10:33 ` Gerd Stolpmann
2016-01-12 13:06 ` Richard W.M. Jones

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).