Using OCaml-5.3's caml_callback_res function

One of my OCaml projects employs some C stub code which applies OCaml callbacks previously registered with Callback.register, using the caml_callback_exn function. If an OCaml callback raises an exception this is detected by applying the Is_exception_result macro to the return value of caml_callback_exn and the exception object is obtained using the Extract_exception macro. The program does not necessarily terminate or reraise in view of such an exception: instead the issue is logged, making use of the caml_format_exception function to provide a textual representation of the exception object, and in some cases then allowed to continue without reraising - in particular where the code is executing in an event loop and there is no OCaml code which can sensibly catch the exception further down the stack if it were to be reraised.

I am aware of the problems with caml_callback_exn (which are dealt with in the manner recommended in the manual), and although the code is correct I have been considering moving to OCaml-5.3’s new caml_callback_res function, which returns a caml_result type. However I have not managed to work out how to obtain the exception object from its return value in order to apply caml_format_exception to log it.

According to the documentation, the public API for the caml_result type comprises the Result_value and Result_exception macros to construct caml_result objects, and the caml_result_is_exception and caml_get_value_or_raise functions to consume them. In the case of an exception the C exception object in fact resides in the ‘data’ field of the caml_result_private C struct, but as the name suggests that struct’s fields are not part of the public API. The caml_get_value_or_raise function is available, but if the caml_result_is_exception function returns true then it always reraises, which is not what I want.

Does anyone know if there is any way around this without using non-public API?

As you point out, this does not seem possible at the moment. I think an issue upstream GitHub · Where software is built would be useful.

Cheers,
Nicolas

This sounds indeed like an unfortunate blind spot on my part in #13013, apologies.

My main reason to leave some parts of the representation abstract/private was to leave the door open to supporting effect handlers in the feature – a “third case” could be added to the structure, which is a pair of an effect operation and a captured continuation. Presumably in this case get_value_or_raise would propagate the effect up to the caller. In this case there would not necessarily be an exception payload to return.

I’m not sure what would be a reasonable API to let users access the exception payload, if/when we want to leave the door open to such an extension.

Wouldn’t it have been better to have caml_result_is_exception return a value*, with the exception value (if any) or NULL otherwise?

Cheers,
Nicolas

I have raised an issue upstream at caml_callback_res does not provide access to exception payload · Issue #14016 · ocaml/ocaml · GitHub . I have made the issue a feature request rather than a bug. It seems to be a bit of both, so please change this if you think that would better express the point.