Skip to content

Async call to node api #1

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

Closed
sunoru opened this issue Jul 17, 2021 · 4 comments
Closed

Async call to node api #1

sunoru opened this issue Jul 17, 2021 · 4 comments

Comments

@sunoru
Copy link
Owner

sunoru commented Jul 17, 2021

All uv_run calls for the event loop of nodeJS from either idle handles of Julia event loop or scheduled tasks (e.g. by @async) raises RangeError: Maximum call stack size exceeded.

For example,

using NodeCall
import NodeCall: UvRunMode, UV_RUN_NOWAIT

function sometask()
    node"setTimeout(() => console.log('Done'), 2000)"
    loop = node_uvloop()
    @async let ret = 1
        while ret != 0
            sleep(0.5)  # or `yeild()` to make the task not blocking
            ret = @ccall :libjlnode.uv_run(loop::Ptr{Cvoid}, UV_RUN_NOWAIT::UvRunMode)::Cint
        end
    end
end

p = sometask()
wait(p)

throws

undefined:0


RangeError: Maximum call stack size exceeded
Thrown at:

No matter which UvRunMode is used.

@sunoru sunoru mentioned this issue Jul 20, 2021
18 tasks
@sunoru sunoru changed the title Promises Async call to livnode.uv_run Jul 20, 2021
@sunoru sunoru changed the title Async call to livnode.uv_run Async call to libnode.uv_run Jul 20, 2021
@sunoru sunoru changed the title Async call to libnode.uv_run Async call to node api Jul 20, 2021
@sunoru
Copy link
Owner Author

sunoru commented Jul 20, 2021

Actually, any async functions that invoke any node-API would throw this. It is because the API must be used in the main thread.

Even showing js values in REPL will throw this error:

julia> using NodeCall
julia> a = node"()=>{}"
┌ Debug: napi_string_expected
└ @ NodeCall ~/pro/julia-packages/NodeCall/src/utils.jl:31
Error showing value of type JsFunction{Nothing}:
ERROR: "Maximum call stack size exceeded"

julia> println(a)
JsFunction{Nothing}: ()=>{}

julia> @async println(a)
┌ Debug: napi_string_expected
└ @ NodeCall ~/pro/julia-packages/NodeCall/src/utils.jl:31
Task (failed) @0x00007fe0ab53fc70
Maximum call stack size exceeded

@sunoru
Copy link
Owner Author

sunoru commented Aug 7, 2021

Try using N-API's async APIs.

@sunoru
Copy link
Owner Author

sunoru commented Aug 10, 2021

https://nodejs.org/docs/latest-v14.x/api/n-api.html#n_api_asynchronous_thread_safe_function_calls

We probably have to invoke by napi_threadsafe_function.

Maybe it's not worth supporting @async, since we can always use @node_async to let NodeJS control the event loop.

Perhaps a function can be provided to wrap a Task with an async context?

I'm still not sure how the other napi_ functions should be used in an async environment. Will test later.

@sunoru
Copy link
Owner Author

sunoru commented Aug 11, 2021

Instead of wrapping Tasks, we can directly modify napi_call to invoke napi_create_threadsafe_function if current_task() != global_task().

See the threading branch and https://github.com/sunoru/jlnode/tree/threading

@sunoru sunoru closed this as completed Aug 10, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant