Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

can't receive function parameters from ocaml5 runtime #148

Closed
tremon015 opened this issue Nov 29, 2023 · 3 comments
Closed

can't receive function parameters from ocaml5 runtime #148

tremon015 opened this issue Nov 29, 2023 · 3 comments

Comments

@tremon015
Copy link

I suspect I'm jumping the gun here, but it doesn't appear possible to reliably receive parameter values from the ocaml5 runtime: the sys::Values don't match what is sent from ocaml. Has the ABI changed, perhaps?

First off, every ocaml::func seems to end in a segfault when unpacking the passed parameters, like this one:

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7f74968 in ocaml::conv::::from_value

Using a native_func gives some more insight into what's happening:

#[ocaml::native_func]
#[ocaml::sig("int -> int -> int -> int -> int")]
pub fn select(sel: Value, fst: Value, snd: Value, ext: Value) -> Value {
   eprintln!("select: sel={:?}, fst={:?}, snd={:?}, ext={:?}", sel, fst, snd, ext);
   let sel = unsafe { sel.int_val() };
   if sel == 0 {
      fst
   }
   else {
      snd
   }
}
   let res = LLc.select 1 2 3 4 in
   traceln "select result: %d" res;

which gives the following output:

select: sel=Raw(5), fst=Raw(9), snd=Root(0x0), ext=Raw(93824995897992)
Program received signal SIGSEGV, Segmentation fault

These values appear consistent over multiple runs, so I don't think it's reading uninitialized memory, just the wrong locations.

I'll supply a gdb backtrace, but I suspect it's of little value given the parameter values above:

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7f6fce3 in ocaml_boxroot_sys::boxroot_get (br=...)
    at $HOME/.cargo/registry/src/index.crates.io-6f17d22bba15001f/ocaml-boxroot-sys-0.3.0/src/lib.rs:24
24	    *(core::cell::UnsafeCell::raw_get(boxroot_get_ref(br)))
(gdb) bt
#0  0x00007ffff7f6fce3 in ocaml_boxroot_sys::boxroot_get (br=...)
    at $HOME/.cargo/registry/src/index.crates.io-6f17d22bba15001f/ocaml-boxroot-sys-0.3.0/src/lib.rs:24
#1  0x00007ffff7f7146d in ocaml::root::Root::get (self=0x7fffffffe4e8) at src/root.rs:34
#2  0x00007ffff7f6f1c6 in ocaml::value::Value::raw (self=0x7fffffffe4e0)
    at src/value.rs:163
#3  0x00007ffff7f6c0e3 in llc::select (sel=..., fst=..., snd=..., ext=...) at lib.rs:118
#4  <signal handler called>
#5  0x0000555555663793 in camlDune__exe__Main.entry () at src/controller/main.ml:180
#6  0x000055555565f21b in caml_program ()

On the other hand, returning complex values from Rust to OCaml works fine:

      let mut tuple = Value::alloc_tuple(2);
      ocaml::body!(gc: {
         tuple.store_field(gc, 0, &val1);
         tuple.store_field(gc, 1, &val2);
         Value::some(gc, tuple)
      })

This value gets received fine as an (int * int) option on the ocaml side.

This is using

  • ocaml-rs from {git = "https://github.com/zshipko/ocaml-rs", branch="ocaml5"}
  • rustc 1.70.0 (90c541806 2023-05-31)
  • OCaml version 5.0.0

But I get the same results in a clean ocaml 5.1.0 switch.

@tremon015
Copy link
Author

tremon015 commented Nov 29, 2023

nosing around the memory area, I can see the correct values appearing in memory (twice even), but I know too little about either OCaml's or Rust's memory layout to diagnose this issue any further:

0x7fffffffe480:	0x03	0x00	0x00	0x00	0x00	0x00	0x00	0x00
0x7fffffffe488:	0x05	0x00	0x00	0x00	0x00	0x00	0x00	0x00
0x7fffffffe490:	0x03	0x00	0x00	0x00	0x00	0x00	0x00	0x00
0x7fffffffe498:	0x05	0x00	0x00	0x00	0x00	0x00	0x00	0x00
0x7fffffffe4a0:	0x07	0x00	0x00	0x00	0x00	0x00	0x00	0x00
0x7fffffffe4a8:	0x09	0x00	0x00	0x00	0x00	0x00	0x00	0x00
0x7fffffffe4b0:	0x07	0x00	0x00	0x00	0x00	0x00	0x00	0x00
0x7fffffffe4b8:	0x09	0x00	0x00	0x00	0x00	0x00	0x00	0x00

@tremon015
Copy link
Author

tremon015 commented Nov 30, 2023

ok, taking a look at what native_func is supposed to do: I can get it working if I change the Rust function lead-in to this:

pub fn select(sel: ocaml::Raw, fst: ocaml::Raw, snd: ocaml::Raw, ext: ocaml::Raw) -> Value {
   let sel = ocaml::Value::Raw(sel.into());
   let fst = ocaml::Value::Raw(fst.into());
   let snd = ocaml::Value::Raw(snd.into());
   let ext = ocaml::Value::Raw(ext.into());
   eprintln!("select: sel={:?}, fst={:?}, snd={:?}, ext={:?}", sel, fst, snd, ext);

This gives the expected result

select: sel=Raw(3), fst=Raw(5), snd=Raw(7), ext=Raw(9)

And I no longer get a segfault on return. So it seems that the macro no longer properly wraps the function parameters?

@zshipko
Copy link
Owner

zshipko commented Aug 21, 2024

Sorry for the delayed reply - this makes sense to me because ocaml::native_func only works with ocaml::Raw - ocaml::func should be used if you want to be able to use ocaml::Value parameters.

@zshipko zshipko closed this as completed Aug 21, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants