Skip to content

Thread dead lock when napi_call_threadsafe_function in some case #58723

Open
@milkpotatoes

Description

@milkpotatoes

Version

No response

Platform


Subsystem

No response

What steps will reproduce the bug?

codes under here.
when call counts greater than max_queue_size and queue is already filling, the thread maybe sleeping until next times tsfn queue is fuling or release is called.

Napi::Value Tsfn(const Napi::CallbackInfo &info) {
  Napi::Env env = info.Env();
  std::atomic<uint32_t> *extraQueuedCounts = new std::atomic<uint32_t>{0};
  napi_threadsafe_function tsfn = nullptr;
  napi_create_threadsafe_function(
      env, nullptr, nullptr, Napi::String::New(env, "hello"), MAX_QUEUE_SIZE, 1,
      nullptr, nullptr, nullptr,
      [](napi_env, napi_value, void *, void *data) {
        std::cout << "executed: " << (uintptr_t)data << std::endl;
      },
      &tsfn);
  // It fulled queue of tsfn
  for (uint32_t i = 0; i < MAX_QUEUE_SIZE; i++) {
    napi_call_threadsafe_function(tsfn, (void *)uintptr_t(i),
                                  napi_tsfn_blocking);
  }
  for (uint32_t i = 0; i < MAX_QUEUE_SIZE; i++) {
    std::thread(
        [&i](napi_threadsafe_function tsfn, std::atomic<uint32_t> *counter) {
          std::cout << "waiting: " << gettid() << std::endl;
          napi_call_threadsafe_function(tsfn, (void *)uintptr_t(i + 3),
                                        napi_tsfn_blocking);
          (*counter)++;
          std::cout << "called: " << gettid() << std::endl;
          // release tsfn after all task queued
          if (counter->load() == MAX_QUEUE_SIZE) {
            napi_release_threadsafe_function(tsfn, napi_tsfn_release);
          }
        },
        tsfn, extraQueuedCounts)
        .detach();
  }
  std::cout << "queued count: " << extraQueuedCounts->load() << std::endl;
  return env.Undefined();
}

How often does it reproduce? Is there a required condition?

sometimes

What is the expected behavior? Why is that the expected behavior?

thread should be awake if queue is not filled

What do you see instead?

thread is blocked

Additional information

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    node-apiIssues and PRs related to the Node-API.

    Type

    No type

    Projects

    Status

    Need Triage

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions