Make the runtime interruptible (similar to await/yield)

Abierto
#5,435 4 comentarios 0 reacciones 1 asignado Ver en GitHub

@youknowone ya está trabajando en esto.

Desde el 9/11/2024.

Evaluación

Este issue todavía no se ha evaluado.

Descripción

C-enhancement

Summary

Make it possible to return from a VM even though the script in there is still not complete.

Expected use case

We're running RustPython within a WASM module in a WebWorker, so it's essentially running in it's own dedicated thread. The Script therein has the capability to send messages to other WebWorkers via channels and other WebWorkers can send back their responses. The Responses will normally trigger an event handler (onmessage) in the Webworker so that the messages can be processed.

Due to the single-threaded nature of JavaScript that event handler will never be executed unless we give back control to the underlying runtime. In our case the would mean we need to somehow return from the WASM-call and thus interrupting the running Python VM.

Possible approaches

I could imagine three ways to support temporary interruption:

Preemptively

After calling enter the underlying VM executes a bunch of instructions (maybe a fixed number or with a timeout) and returns with a value indicating the execution is not complete and can be resumed (e.g. a continuation token). The caller can then perform other duties and resume the execution later (e.g. by calling a new resume-method)

Cooperatively

The Python code can call some built-in function (e.g. await, yield) allowing the VM to return in mid-execution. Otherwise this is the same as above

async

The enter-method becomes async and calls into a #[pyfunction] will be async as well. This is similar to the cooperative approach, but permits easier integration with Rusts async ecosystem

Alternatives

I'll continue my research whether this can be solved without altering RustPython. So far I could think of the following workarounds:

  • maybe wasm_bindgen supports some feature to interrupt the execution of a WASM module in a way that makes it possible to temporarily yield to the JavaScript-Runtime.
  • Instead of using JavaCript-Channels I could try to build my own data-exchange framework based on SharedMemory and Atomics. So far this has been an ergonomic nightmare but it should work in theory.
  • Use multithreading in WASM. Last time I tried this I ended up with a very fragile setup that was very hard to run reliably. The ergonomics from the Rust side would be very good, though. Maybe things have improved in the meantime.

Here is an example how wasmtime solves this: https://docs.rs/wasmtime/latest/wasmtime/struct.Config.html#method.consume_fuel

BTW: thanks a lot for this awesome crate ❤️ impressive work!

Lenguaje dominante
Rust
Estrellas
22.4k
Forks
1.5k
Merge medio
14 h 42 min
PR fusionados (30 d)
174

Guía de contribución

Abrir la guía de contribución

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de RustPython/RustPython

Todos los issues de RustPython/RustPython

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.