Skip to content

Async call to node api #1

Closed
Closed

Description

@sunoru

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.

Activity

  1. changed the title [-]Promises[/-] [+]Async call to livnode.uv_run[/+] on Jul 20, 2021
  2. changed the title [-]Async call to livnode.uv_run[/-] [+]Async call to libnode.uv_run[/+] on Jul 20, 2021
  3. changed the title [-]Async call to libnode.uv_run[/-] [+]Async call to node api[/+] on Jul 20, 2021
  4. sunoru commented on Jul 20, 2021

    @sunoru
    OwnerAuthor

    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
  5. sunoru commented on Aug 7, 2021

    @sunoru
    OwnerAuthor

    Try using N-API's async APIs.

  6. sunoru commented on Aug 10, 2021

    @sunoru
    OwnerAuthor

    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.

  7. sunoru commented on Aug 11, 2021

    @sunoru
    OwnerAuthor

    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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions