neon-bindings / neon

Rust bindings for writing safe and fast native Node.js modules.
https://www.neon-bindings.com/
Apache License 2.0
7.98k stars 282 forks source link

When a callback function is called multiple times in a thread, only the first call takes effect #1038

Closed XiaoyuZhann closed 4 months ago

XiaoyuZhann commented 4 months ago

Hello, I tested implementing a udpSocket connection in rust, but I can only receive the first value in js, and then print "un def". The frontend I'm using is Electron and the neon version is 1.0.0

RUST:

fn parse_async(mut cx: FunctionContext) -> JsResult<JsUndefined> {
    let address = cx.argument::<JsString>(0)?.value(&mut cx);
    let callback = cx.argument::<JsFunction>(1)?.root(&mut cx);
    let channel = cx.channel();
    std::thread::spawn(move || {
        let socket = UdpSocket::bind("192.168.2.174:8000").expect("UdpSocket err");
        println!("{}", address);
        let _ = socket.connect(address.clone());
        channel.send(move |mut cx| {
            let callback = callback.clone(&mut cx).to_inner(&mut cx);
            let this = cx.undefined();
            loop {
                let mut buffer = [0u8; 1024];
                socket.recv_from(&mut buffer).expect("failed to receive");
                let data = std::str::from_utf8(&buffer).expect("failed to convertto String");
                println!("rust: {}", data);
                let args = vec![cx.string(data).upcast()];
                callback.call(&mut cx, this, args)?;
            }
            Ok(())
        });
    });
    Ok(cx.undefined())
}

JS:

import { parentPort } from 'worker_threads'
import ext from '../../rs-core/index.node'

function call(data) {
    parentPort?.postMessage(data)
    console.log(data)
}

parentPort?.on('message', data => {
    ext.parse_async(data, call)
})

The following is the message that is printed when the UDP server sends "test".

"192.168.2.174:8080"
rust: test
test                 // js print
rust: test
un def              // js print
kjvalencik commented 4 months ago

This code is looping in the channel callback (main js thread) which is blocking the event loop. This might be the cause.

Can you try moving the loop outside of the channel.send callback?

XiaoyuZhann commented 4 months ago

This code is looping in the channel callback (main js thread) which is blocking the event loop. This might be the cause.

Can you try moving the loop outside of the channel.send callback?

Thanks for the pointers, it works