From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Original-To: caml-list@sympa.inria.fr Delivered-To: caml-list@sympa.inria.fr Received: from mail2-relais-roc.national.inria.fr (mail2-relais-roc.national.inria.fr [192.134.164.83]) by sympa.inria.fr (Postfix) with ESMTPS id DDBC77FDC8 for ; Tue, 12 Jan 2016 10:12:34 +0100 (CET) IronPort-PHdr: 9a23:j74zWhUOBdWvoW3u5SwL4HkHOSbV8LGtZVwlr6E/grcLSJyIuqrYZhOOt8tkgFKBZ4jH8fUM07OQ6PC+Hzxaqsne+Fk5M7VyFDY9wf0MmAIhBMPXQWbaF9XNKxIAIcJZSVV+9Gu6O0UGUOz3ZlnVv2HgpWVKQka3CwN5K6zPF5LIiIzvjqbpq8OVM18D22X1SIgxBSv1hD2ZjtMRj4pmJ/R54TryiVwMRd5rw3h1L0mYhRf265T41pdi9yNNp6BprJYYAu2pN5g/GPZTBTEidmQ0/9HDtB/ZTALJ6GFWGjEdmx9MRgzE9w3SX5HrsyK8uPAriweAOsijB5Y5RDSr4rpwUxLyzG8iPiQl8Wedwph1hbhHoRTnoRFiw4fZfZqOOeBWZaLQeN4cXixKWcMHBH8JOZ+1c4ZaV7lJBu1ftYSo/1Y= Authentication-Results: mail2-smtp-roc.national.inria.fr; spf=None smtp.pra=martin.neuhaeusser@siemens.com; spf=None smtp.mailfrom=martin.neuhaeusser@siemens.com; spf=None smtp.helo=postmaster@gecko.sbs.de Received-SPF: None (mail2-smtp-roc.national.inria.fr: no sender authenticity information available from domain of martin.neuhaeusser@siemens.com) identity=pra; client-ip=194.138.37.40; receiver=mail2-smtp-roc.national.inria.fr; envelope-from="martin.neuhaeusser@siemens.com"; x-sender="martin.neuhaeusser@siemens.com"; x-conformance=sidf_compatible Received-SPF: None (mail2-smtp-roc.national.inria.fr: no sender authenticity information available from domain of martin.neuhaeusser@siemens.com) identity=mailfrom; client-ip=194.138.37.40; receiver=mail2-smtp-roc.national.inria.fr; envelope-from="martin.neuhaeusser@siemens.com"; x-sender="martin.neuhaeusser@siemens.com"; x-conformance=sidf_compatible Received-SPF: None (mail2-smtp-roc.national.inria.fr: no sender authenticity information available from domain of postmaster@gecko.sbs.de) identity=helo; client-ip=194.138.37.40; receiver=mail2-smtp-roc.national.inria.fr; envelope-from="martin.neuhaeusser@siemens.com"; x-sender="postmaster@gecko.sbs.de"; x-conformance=sidf_compatible X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: A0DtAAC3wpRWnCglisJehAxtBohTsz2BZiKFbQKBKToSAQEBAQEBAQEQAQEBAQEICwkJISMLgi2CCQU6JisBKhQFPSYBBBuIJgQBCZ9GoCMhhliDeYVbg0uBGwWXEwGFQpE6hViOUykMglUkgUByhSkBgQcBAQE X-IPAS-Result: A0DtAAC3wpRWnCglisJehAxtBohTsz2BZiKFbQKBKToSAQEBAQEBAQEQAQEBAQEICwkJISMLgi2CCQU6JisBKhQFPSYBBBuIJgQBCZ9GoCMhhliDeYVbg0uBGwWXEwGFQpE6hViOUykMglUkgUByhSkBgQcBAQE X-IronPort-AV: E=Sophos;i="5.20,556,1444687200"; d="scan'208";a="196850704" Received: from gecko.sbs.de ([194.138.37.40]) by mail2-smtp-roc.national.inria.fr with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 12 Jan 2016 10:12:33 +0100 Received: from mail1.sbs.de (mail1.sbs.de [192.129.41.35]) by gecko.sbs.de (8.15.2/8.15.2) with ESMTPS id u0C9CXFW020876 (version=TLSv1.2 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK) for ; Tue, 12 Jan 2016 10:12:33 +0100 Received: from DEFTHW99ERJMSX.ww902.siemens.net (defthw99erjmsx.ww902.siemens.net [139.22.70.135]) by mail1.sbs.de (8.15.1/8.15.1) with ESMTPS id u0C9CVo0029799 (version=TLSv1 cipher=AES256-SHA bits=256 verify=FAIL) for ; Tue, 12 Jan 2016 10:12:33 +0100 Received: from DENBGAT9ERIMSX.ww902.siemens.net (139.22.70.138) by DEFTHW99ERJMSX.ww902.siemens.net (139.22.70.135) with Microsoft SMTP Server (TLS) id 14.3.266.1; Tue, 12 Jan 2016 10:12:31 +0100 Received: from DENBGAT9EK5MSX.ww902.siemens.net ([169.254.12.138]) by DENBGAT9ERIMSX.ww902.siemens.net ([139.22.70.138]) with mapi id 14.03.0266.001; Tue, 12 Jan 2016 10:12:30 +0100 From: "Neuhaeusser, Martin" To: "caml-list@inria.fr" Thread-Topic: The OCaml garbage collector, finalisers, and the right way of disposing native pointers in C bindings Thread-Index: AdFNGS72eCTGScnoR+Sxf/FDmIVJ1A== Date: Tue, 12 Jan 2016 09:12:30 +0000 Message-ID: <965631B03C670145ABB9F693E51622530D0D763B@DENBGAT9EK5MSX.ww902.siemens.net> Accept-Language: de-DE, en-US Content-Language: de-DE X-MS-Has-Attach: X-MS-TNEF-Correlator: x-originating-ip: [139.22.70.36] Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Subject: [Caml-list] The OCaml garbage collector, finalisers, and the right way of disposing native pointers in C bindings Dear all, during our work on some SMT solver bindings, a couple of question came up r= egarding the behavior of the OCaml garbage collector (see also https://gith= ub.com/Z3Prover/z3/issues/411). Assume we have defined a record type contai= ning a native pointer to some object from an external C-DLL: type ocaml_record =3D { native_ptr np; [... some more fields ...] } When creating an ocaml_record, we register a finalizer that makes the C lib= rary dispose the data belonging to the native pointer once the GC collects = the OCaml record value: let f ocaml_record =3D NativeLib.dispose ocaml_record.np let create [...] =3D let new_ocaml_record =3D { ... } 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 =3D ocaml_record.np NativeLib.native_function (get_native_pointer ocaml_record) However, this has the problem that if ocaml_record has become otherwise unr= eachable, the GC might collect ocaml_record directly after evaluating (get_= native_pointer ocaml_record), triggering the finalizer which disposes the d= ata 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 ac= cess 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, th= e GC must not collect an item that has been "pinned" by the CAMLparamX macr= os, right? 2. One could invent some function that takes an ocaml_record, but does noth= ing with it and whose calls do not get optimized away by the compiler... Ev= aluating such a function after the call to NativeLib.native_function would = prevent the GC from collecting ocaml_record. However, this feels like a ver= y ugly hack.=20 Are there any better ideas? Any help and suggestions are highly appreciated. Best, Martin