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
next 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