Hello Genodians
Benjamin Lamowskis great article "A first complex Rust package" [1] and the attention Rust on Genode received recently on this mailing list motivated me to explore the latest achievements regarding Goa and Rust myself :)
I went straight down experimenting with Rocket, a web framework for Rust and setup a corresponding Goa project [2].
Compiling the "Hello World" example [3] with Goa was a very pleasing experience and at link stage, only two symbols were missing: kqueue and kevent. I added dummy implementations for both calls [4] (and by the way learned about the compat-libc API). Building succeeds now, but obviously fails at runtime: ``` Genode 24.02 <local changes> 17592186044415 MiB RAM and 18997 caps assigned to init [init -> hello_rocket] Warning: Libc RNG not configured [init -> hello_rocket] Warning: __sys_kqueue: kqueue not implemented [init -> hello_rocket] thread 'main' panicked at /home/wonko/.cargo/registry/src/index.crates.io-6f17d22bba15001f/rocket-0.5.0/src/lib.rs:245:10: [init -> hello_rocket] create tokio runtime: Os { code: 78, kind: Unsupported, message: "Function not implemented" } [init -> hello_rocket] note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace [init -> hello_rocket] Error: raise(ABRT) [init] child "hello_rocket" exited with exit value -1 ```
I'm aware that most certainly, there are other roadblocks ahead. However, I'd like to pursue the topic regarding kqueue()/kevent() a bit more since I assume this might be (or has been) a roadblock for porting other applications or runtimes.
- Is it reasonable to add those calls to Genodes libc?
- Or can Rust be instructed not to use those calls but select() instead? I stumbled over the MIO flags `mio_unsupported_force_poll_poll` and `mio_unsupported_force_waker_pipe` [5]. But I'm not versed in Rust and setting `mio_unsupported_force_poll_poll` by naively applying the following patch to Goa leads to `error[E0252]: the name `Waker` is defined multiple times`: ``` diff --git a/share/goa/lib/build/cargo.tcl b/share/goa/lib/build/cargo.tcl index 7c0c52b..78e7e26 100644 --- a/share/goa/lib/build/cargo.tcl +++ b/share/goa/lib/build/cargo.tcl @@ -43,6 +43,8 @@ proc build { } { lappend rustflags -C link-arg=$x }
+ lappend rustflags --cfg mio_unsupported_force_poll_poll + set ::env(RUSTFLAGS) $rustflags set ::env(RUST_STD_FREEBSD_12_ABI) 1 ```
- [1] https://genodians.org/atopia/2023-10-26-a-first-complex-rust-package - [2] https://github.com/rite/goa-projects/tree/hello_rocket - [3] https://rocket.rs/guide/v0.5/getting-started - [4] https://github.com/rite/genode/commit/0219d0543cedd180b082e1ef13dd5d779d7e57... - [5] https://github.com/tokio-rs/mio?tab=readme-ov-file#unsupported-flags
Hi Roman,
Nice to see your interest in Rust on Genode! I finally got around looking into your experiments with Rocket.
I'm afraid there is no easy hotfix for your specific use case. I got around your specific error by adding both Mio flags to cargo.tcl:
lappend rustflags --cfg mio_unsupported_force_poll_poll --cfg mio_unsupported_force_waker_pipe
However down the road compilation failed anyway because the Tokio crate, expecting a kqueue based Mio implementation on FreeBSD, uses AIO, which fails with Mio's poll implementation. Your general approach was correct though, as long as more granular config flag support[1] is not available, there is no alternative to setting the cfg flag globally.
I'm aware that most certainly, there are other roadblocks ahead. However, I'd like to pursue the topic regarding kqueue()/kevent() a bit more since I assume this might be (or has been) a roadblock for porting other applications or runtimes.
- Is it reasonable to add those calls to Genodes libc?
I absolutely agree that implementing support for kqueue()/kevent() in Genode's libc port is the reasonable way forward and I also suspect that future ports will likely benefit from its availability. I have looked into potential stumbling blocks and sketched out a possible implementation. I would be happy to implement at least basic support for the common kevent filters used in Mio (EVFILT_READ, EVFILT_WRITE) and defer implementing some of the more obscure ones. However, to make the Tokio runtime work, it seems we will need to implement support for AIO as well. I haven't really looked into AIO yet and I'm not sure how difficult it will be to make this work, but with the widespread use of Tokio, it will be a prerequisite for many complex Rust packages.
I much appreciate your experiments and if you want to take this further, we do of course welcome contributions to our libc port. While I'm looking forward to extending our Rust support, I'm currently working on other road map milestones and may not get around to working on this before the 24.04 Sculpt release.
Best wishes,
Ben
[1] https://github.com/rust-lang/cargo/issues/10271