-
Notifications
You must be signed in to change notification settings - Fork 29.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
node-api: document node-api shutdown finalization #45903
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -477,11 +477,11 @@ may be called multiple times, from multiple contexts, and even concurrently from | |
multiple threads. | ||
|
||
Native addons may need to allocate global state which they use during | ||
their entire life cycle such that the state must be unique to each instance of | ||
the addon. | ||
their life cycle of an Node.js environment such that the state can be | ||
unique to each instance of the addon. | ||
|
||
To this end, Node-API provides a way to allocate data such that its life cycle | ||
is tied to the life cycle of the Agent. | ||
To this end, Node-API provides a way to associate data such that its life cycle | ||
is tied to the life cycle of a Node.js environment. | ||
|
||
### `napi_set_instance_data` | ||
|
||
|
@@ -509,11 +509,11 @@ napi_status napi_set_instance_data(napi_env env, | |
|
||
Returns `napi_ok` if the API succeeded. | ||
|
||
This API associates `data` with the currently running Agent. `data` can later | ||
be retrieved using `napi_get_instance_data()`. Any existing data associated with | ||
the currently running Agent which was set by means of a previous call to | ||
`napi_set_instance_data()` will be overwritten. If a `finalize_cb` was provided | ||
by the previous call, it will not be called. | ||
This API associates `data` with the currently running Node.js environment. `data` | ||
can later be retrieved using `napi_get_instance_data()`. Any existing data | ||
associated with the currently running Node.js environment which was set by means | ||
of a previous call to `napi_set_instance_data()` will be overwritten. If a | ||
`finalize_cb` was provided by the previous call, it will not be called. | ||
|
||
### `napi_get_instance_data` | ||
|
||
|
@@ -531,13 +531,13 @@ napi_status napi_get_instance_data(napi_env env, | |
|
||
* `[in] env`: The environment that the Node-API call is invoked under. | ||
* `[out] data`: The data item that was previously associated with the currently | ||
running Agent by a call to `napi_set_instance_data()`. | ||
running Node.js environment by a call to `napi_set_instance_data()`. | ||
|
||
Returns `napi_ok` if the API succeeded. | ||
|
||
This API retrieves data that was previously associated with the currently | ||
running Agent via `napi_set_instance_data()`. If no data is set, the call will | ||
succeed and `data` will be set to `NULL`. | ||
running Node.js environment via `napi_set_instance_data()`. If no data is set, | ||
the call will succeed and `data` will be set to `NULL`. | ||
|
||
## Basic Node-API data types | ||
|
||
|
@@ -1798,11 +1798,11 @@ If still valid, this API returns the `napi_value` representing the | |
JavaScript `Object` associated with the `napi_ref`. Otherwise, result | ||
will be `NULL`. | ||
|
||
### Cleanup on exit of the current Node.js instance | ||
### Cleanup on exit of the current Node.js environment | ||
|
||
While a Node.js process typically releases all its resources when exiting, | ||
embedders of Node.js, or future Worker support, may require addons to register | ||
clean-up hooks that will be run once the current Node.js instance exits. | ||
clean-up hooks that will be run once the current Node.js environment exits. | ||
|
||
Node-API provides functions for registering and un-registering such callbacks. | ||
When those callbacks are run, all resources that are being held by the addon | ||
|
@@ -1928,6 +1928,22 @@ the hook from being executed, unless it has already started executing. | |
This must be called on any `napi_async_cleanup_hook_handle` value obtained | ||
from [`napi_add_async_cleanup_hook`][]. | ||
|
||
### Finalization on the exit of the Node.js environment | ||
|
||
The Node.js environment may be torn down at an arbitrary time as soon as | ||
possible with JavaScript execution disallowed, like on the request of | ||
[`worker.terminate()`][]. When the environment is being torn down, the | ||
registered `napi_finalize` callbacks of JavaScript objects, Thread-safe | ||
functions and environment instance data are invoked immediately and | ||
independently. | ||
|
||
The invocation of `napi_finalize` callbacks are scheduled after the manually | ||
registered cleanup hooks. In order to ensure a proper order of addon | ||
finalization during environment shutdown to avoid use-after-free in the | ||
`napi_finalize` callback, addons should register a cleanup hook with | ||
`napi_add_env_cleanup_hook` and `napi_add_async_cleanup_hook` to manually | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you expand a bit here? Is the suggestion to use the hooks instead of napi_finalize callback? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This part is specifically focused on the finalization at shutdown. Still, addons should set an However, their Normally, we expect the order to be:
However, when the environment is shutting down, the order would be:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @legendecas Does this mean that I am supposed to maintain a central directory of all There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @legendecas in particular, if I use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
If the ThreadSafeFunction is saved as a field of a c++ ObjectWrap, it should be released in the destructor of the ObjectWrap. So it is sufficient for an add-on to keep track of ObjectWraps and released them in a
This is how |
||
release the allocated resource in a proper order. | ||
|
||
## Module registration | ||
|
||
Node-API modules are registered in a manner similar to other modules | ||
|
@@ -6452,6 +6468,7 @@ the add-on's file name during loading. | |
[`process.release`]: process.md#processrelease | ||
[`uv_ref`]: https://docs.libuv.org/en/v1.x/handle.html#c.uv_ref | ||
[`uv_unref`]: https://docs.libuv.org/en/v1.x/handle.html#c.uv_unref | ||
[`worker.terminate()`]: worker_threads.md#workerterminate | ||
[async_hooks `type`]: async_hooks.md#type | ||
[context-aware addons]: addons.md#context-aware-addons | ||
[docs]: https://github.com/nodejs/node-addon-api#api-documentation | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you mean these run in parallel?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, their
napi_finalize
callbacks can be run in an interleaving pattern, on the JavaScript thread.