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>
This commit is contained in:
Gabriel Schulhof
2020-04-06 10:16:15 -07:00
parent b82d72c199
commit aeb7084fe6
7 changed files with 100 additions and 10 deletions

View File

@@ -457,6 +457,7 @@ typedef enum {
napi_date_expected,
napi_arraybuffer_expected,
napi_detachable_arraybuffer_expected,
napi_would_deadlock,
} napi_status;
```
@@ -5095,6 +5096,12 @@ preventing data from being successfully added to the queue. If set to
`napi_call_threadsafe_function()` never blocks if the thread-safe function was
created with a maximum queue size of 0.
As a special case, when `napi_call_threadsafe_function()` is called from the
main thread, it will return `napi_would_deadlock` if the queue is full and it
was called with `napi_tsfn_blocking`. The reason for this is that the main
thread is responsible for reducing the number of items in the queue so, if it
waits for room to become available on the queue, then it will deadlock.
The actual call into JavaScript is controlled by the callback given via the
`call_js_cb` parameter. `call_js_cb` is invoked on the main thread once for each
value that was placed into the queue by a successful call to
@@ -5231,6 +5238,12 @@ This API may be called from any thread which makes use of `func`.
<!-- YAML
added: v10.6.0
napiVersion: 4
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/32689
description: >
Return `napi_would_deadlock` when called with `napi_tsfn_blocking` from
the main thread and the queue is full.
-->
```C
@@ -5248,9 +5261,13 @@ napi_call_threadsafe_function(napi_threadsafe_function func,
`napi_tsfn_nonblocking` to indicate that the call should return immediately
with a status of `napi_queue_full` whenever the queue is full.
This API will return `napi_would_deadlock` if called with `napi_tsfn_blocking`
from the main thread and the queue is full.
This API will return `napi_closing` if `napi_release_threadsafe_function()` was
called with `abort` set to `napi_tsfn_abort` from any thread. The value is only
added to the queue if the API returns `napi_ok`.
called with `abort` set to `napi_tsfn_abort` from any thread.
The value is only added to the queue if the API returns `napi_ok`.
This API may be called from any thread which makes use of `func`.