diff --git a/src/node_api.cc b/src/node_api.cc index 552538c6f05fcf..18adb1aadb245b 100644 --- a/src/node_api.cc +++ b/src/node_api.cc @@ -110,6 +110,34 @@ static inline void trigger_fatal_exception( node::errors::TriggerUncaughtException(env->isolate, local_err, local_msg); } +// `uv_thread_self()` returns 0 on Windows for threads that were not created +// using `uv_thread_start()`. Thus, for correct comparison, we need to use +// `GetCurrentThreadId()`. +class ThreadID { + public: +#ifdef _WIN32 + typedef DWORD thread_id_t; + ThreadID() : _tid(GetCurrentThreadId()) {} + inline bool operator==(const ThreadID& other) const { + return _tid == other._tid; + } +#else + typedef uv_thread_t thread_id_t; + ThreadID() : _tid(uv_thread_self()) {} + inline bool operator==(const ThreadID& other) const { + return static_cast(uv_thread_equal(&_tid, &other._tid)); + } +#endif // _WIN32 + + ThreadID(const ThreadID&) = delete; + ThreadID(ThreadID&&) = delete; + void operator= (const ThreadID&) = delete; + void operator= (const ThreadID&&) = delete; + + private: + thread_id_t _tid; +}; + class ThreadSafeFunction : public node::AsyncResource { public: ThreadSafeFunction(v8::Local func, @@ -129,7 +157,6 @@ class ThreadSafeFunction : public node::AsyncResource { is_closing(false), context(context_), max_queue_size(max_queue_size_), - main_thread(uv_thread_self()), env(env_), finalize_data(finalize_data_), finalize_cb(finalize_cb_), @@ -149,14 +176,14 @@ class ThreadSafeFunction : public node::AsyncResource { napi_status Push(void* data, napi_threadsafe_function_call_mode mode) { node::Mutex::ScopedLock lock(this->mutex); - uv_thread_t current_thread = uv_thread_self(); + ThreadID current_thread; while (queue.size() >= max_queue_size && max_queue_size > 0 && !is_closing) { if (mode == napi_tsfn_nonblocking) { return napi_queue_full; - } else if (uv_thread_equal(¤t_thread, &main_thread)) { + } else if (current_thread == main_thread) { return napi_would_deadlock; } cond->Wait(lock); @@ -438,7 +465,7 @@ class ThreadSafeFunction : public node::AsyncResource { // means we don't need the mutex to read them. void* context; size_t max_queue_size; - uv_thread_t main_thread; + ThreadID main_thread; // These are variables accessed only from the loop thread. v8impl::Persistent ref;