"No reactor running" when using Tokio + FFI and dynamic dispatch from a trait

43 Views Asked by At

I know, quite the use case.

I am trying to build a plugin API for my application where the contract between plugins and the main executer are defined with a trait. I will use the stable_abi crate to achieve this but for now I am using libloading with Rust's built in FFI capabilities.

At its most basic I have a dylib crate (the plugin) and a bin crate (the executor). The executor consumes the dylib and calls methods on it.

The most basic example is this:

/plugin
/executor

/target
  /debug
    executor
    plugin.so
// plugin/src/lib.rs
#[no_mangle]
pub extern fn add(left: usize, right: usize) -> usize {
    left + right
}
// executor/src/main.rs
fn main() {
  let exe_path = std::env::current_exe().unwrap();
  let exe_dir = exe_path.parent().unwrap();
  let lib_path = exe_dir.join("libplugin.so");

  unsafe {
    let lib = libloading::Library::new(&lib_path).unwrap();
    let add: libloading::Symbol<unsafe fn(usize, usize) -> usize> = lib.get(b"add").unwrap();
    println!("{}", add(1, 1));
  }
}

I then progressively add layers to it, moving towards a trait with methods that return futures:

Tokio fails with:

thread '<unnamed>' panicked at c/src/lib.rs:12:13:
there is no reactor running, must be called from the context of a Tokio 1.x runtime

This failure occurs in tokio::task::spawn within the AddMachine struct, but only when the .add() method is called when it's in the form of a Box<dyn Adder>.

Why is this and is there a way around it?

0

There are 0 best solutions below