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

Rust async function stuck indefinitely when called from js #3545

Closed
zlindner opened this issue Dec 31, 2023 · 4 comments
Closed

Rust async function stuck indefinitely when called from js #3545

zlindner opened this issue Dec 31, 2023 · 4 comments
Labels
bug Something isn't working

Comments

@zlindner
Copy link

zlindner commented Dec 31, 2023

Describe the bug
Async rust functions called from js seem to hang/get stuck forever when using tokio.

To Reproduce
Spawn tasks in a loop that execute a simple javascript script which calls a single function sleep that is a rust async native function:

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    loop {
        tokio::spawn(async move {
            let mut context = Context::default();

            context
                .register_global_callable(
                    js_string!("sleep"),
                    0,
                    NativeFunction::from_async_fn(do_something_async),
                )
                .unwrap();

            let script = r"
            function test() {
                sleep();
                return true;
            }";

            context.eval(Source::from_bytes(script)).unwrap();
            let result = context.eval(Source::from_bytes("test()")).unwrap();
            println!("{:?}", result);
        });
    }
}

fn do_something_async(
    _this: &JsValue,
    _args: &[JsValue],
    _context: &mut Context,
) -> impl Future<Output = JsResult<JsValue>> {
    async move {
        println!("Start sleeping...");
        sleep(Duration::from_secs(1)).await;
        println!("Done!");
        Ok(JsValue::Boolean(true))
    }
}

This results in the below output: (this is all the output I get, all 8 "Start sleeping..." lines get printed immediately then gets stuck forever)

Start sleeping...
Start sleeping...
Start sleeping...
Start sleeping...
Start sleeping...
Start sleeping...
Start sleeping...
Start sleeping...

Any ideas why this is the case? Not sure if I'm doing something wrong or if this is a bug. It seems to work fine if I either remove the tokio::spawn altogether and just run in the main function, or await the JoinHandle for the tasks.

Build environment (please complete the following information):

  • OS: macOS
  • Version: Tested both 0.17.3 and main branch, same behaviour
  • Rustc version: rustc 1.75.0 (82e1608df 2023-12-21)
@zlindner zlindner added the bug Something isn't working label Dec 31, 2023
@jedel1043
Copy link
Member

jedel1043 commented Dec 31, 2023

Remember that all tokio futures must be polled by a tokio executor to progress. The default job executor doesn't use an async executor, it only blocks on all future jobs.

If you need this functionality, you'd have to override the JobQueue and use a thread-local tokio executor to push all futures forward.

@zlindner
Copy link
Author

Ok makes sense, thanks for the help :). Will try it out, if I get something working will create a PR adding an example.

@jedel1043
Copy link
Member

Good! Also, remember to call run_jobs_async to push the futures forward, or else the context will just evaluate the code without evaluating any of the futures and promises

@jedel1043
Copy link
Member

Will close this since the original question was resolved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants