diff options
author | Gabriel Schulhof <gabriel.schulhof@intel.com> | 2020-04-06 20:16:15 +0300 |
---|---|---|
committer | Gabriel Schulhof <gabriel.schulhof@intel.com> | 2020-04-09 12:41:28 +0300 |
commit | aeb7084fe6446350ec032e9819746126811bf44f (patch) | |
tree | b1173c9ecd5c049f5af7298c181e587b437cd60d /src/node_api.cc | |
parent | b82d72c199e70a0c9fbeb6c06715ef8120b3de2f (diff) |
n-api: detect deadlocks in thread-safe function
We introduce status `napi_would_deadlock` to be used as a return status
by `napi_call_threadsafe_function` if the call is made with
`napi_tsfn_blocking` on the main thread and the queue is full.
PR-URL: https://github.com/nodejs/node/pull/32689
Fixes: https://github.com/nodejs/node/issues/32615
Signed-off-by: Gabriel Schulhof <gabriel.schulhof@intel.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: David Carlier <devnexen@gmail.com>
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com>
Diffstat (limited to 'src/node_api.cc')
-rw-r--r-- | src/node_api.cc | 5 |
1 files changed, 5 insertions, 0 deletions
diff --git a/src/node_api.cc b/src/node_api.cc index fad9cf72a97..552538c6f05 100644 --- a/src/node_api.cc +++ b/src/node_api.cc @@ -129,6 +129,7 @@ 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_), @@ -148,12 +149,15 @@ 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(); 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)) { + return napi_would_deadlock; } cond->Wait(lock); } @@ -434,6 +438,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; // These are variables accessed only from the loop thread. v8impl::Persistent<v8::Function> ref; |