[BLOG] OCaml FFI Sharp Edges and How to Avoid Them

Wrote another blog post about my adventures in Godotcaml. Check it out if you’re interested in some details of memory management with a Ctypes FFI. Would love to hear input to some of the questions asked in the post, too, if you’d like!

Matt

4 Likes

Have you tried using Sys.opaque_identity to keep the value alive? (That is the approach we’ve taken in XAPI a while ago CA-293399: Corrupted PCI information in xapi database by krizex · Pull Request #3669 · xapi-project/xen-api · GitHub)

The value lifetime issues you encountered sound very similar to the ones we encountered using strings in the XAPI project (documented here: Make management of C-memory allocated from OCaml more explicit · Issue #571 · yallop/ocaml-ctypes · GitHub)

I haven’t thought about using explicit Ctypes.Root management though.

1 Like

@edwin, this is perfect. I notice in XAPI you ended up using ignore (opaque_identity (hd [x])). I wonder if you could instead replace this with two applications of opaque_identity. Indeed, I will be testing the function let keep_alive x = ignore (Sys.opaque_identity (Sys.opaque_identity x)) hopefully later today or tomorrow. Cheers for this!

Matt

If one application of opaque_identity doesn’t work, then there is probably something wrong with the approach. It is supposed to make the optimizer forget about the value, and if it didn’t then using 2 would likely just hide a bug and potentially break later when the optimizer becomes smarter.

The manual documents it as “For the purposes of optimization, opaque_identity behaves like an unknown (and thus possibly side-effecting) function.”, so I think that implies the compiled code should keep the value registered/alive, OTOH it does say that the function disappears completely at runtime, so I’m not 100% sure this approach would keep working.

While I agree, it seems the same can be said about hd [x], no? I will test with a single application too!

Yes, I don’t think that List.hd [x] is necessary either, the opaque identity on its own should be, and if it isn’t then this approach is still very fragile, but I haven’t tested this lately.

@edwin I’ve marked your answer as a solution, since in my testing it works perfectly with just the let keep_alive x = ignore (Sys.opaque_identity x). I will likely open a PR with Ctypes, as this seems like a really handy function to know about, document, and have around.

1 Like

@edwin Just FYI, as discussed in Documentation update regarding the safety of `Sys.opaque_identity` with respect to garbage collection · Issue #13287 · ocaml/ocaml · GitHub, until Keep Sys.opaque_identity in Cmm and Mach by stedolan · Pull Request #9412 · ocaml/ocaml · GitHub this solution would not have worked, which is likely why in XAPI you found it necessary to use hd, which can throw an exception. It should work fine now without the hd, and would save you an allocation (if you care about that). Cheers again.

2 Likes