caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: "Neuhaeusser, Martin" <martin.neuhaeusser@siemens.com>
To: "caml-list@inria.fr" <caml-list@inria.fr>
Subject: [Caml-list] The OCaml garbage collector, finalisers, and the right way of disposing native pointers in C bindings
Date: Tue, 12 Jan 2016 09:12:30 +0000	[thread overview]
Message-ID: <965631B03C670145ABB9F693E51622530D0D763B@DENBGAT9EK5MSX.ww902.siemens.net> (raw)

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

             reply	other threads:[~2016-01-12  9:12 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-01-12  9:12 Neuhaeusser, Martin [this message]
2016-01-12  9:37 ` Kim Nguyễn
2016-01-12 10:33 ` Gerd Stolpmann
2016-01-12 13:06 ` Richard W.M. Jones

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=965631B03C670145ABB9F693E51622530D0D763B@DENBGAT9EK5MSX.ww902.siemens.net \
    --to=martin.neuhaeusser@siemens.com \
    --cc=caml-list@inria.fr \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).