-
-
Notifications
You must be signed in to change notification settings - Fork 493
Closed
Labels
Description
When calling N-API based async code (in particular written with none-addon-api) from a process exit hook process.on("exit") it leads to a fatal error.
This is very easy to reproduce. For example, take the asyncworker.js tests and put the last block within a process.on("exit") callback. Like this
Running as node --expose-gc test/asyncworker.js the process is aborted and I see the following stack trace. Tested with Node.js 12.12.0 on macOS 10.14.
FATAL ERROR: Error::Error napi_create_reference
1: 0x100b6a52a node::Abort() (.cold.1) [/usr/local/bin/node]
2: 0x100081f70 node::FatalError(char const*, char const*) [/usr/local/bin/node]
3: 0x100082098 node::OnFatalError(char const*, char const*) [/usr/local/bin/node]
4: 0x100081f79 node::OnFatalError(char const*, char const*) [/usr/local/bin/node]
5: 0x100060554 napi_open_callback_scope [/usr/local/bin/node]
6: 0x104c01746 Napi::Error::Fatal(char const*, char const*) [/Users/rolftimmermans/Code/vendor/node-addon-api/test/build/Release/binding.node]
7: 0x104c0588b Napi::Error::New(napi_env__*) [/Users/rolftimmermans/Code/vendor/node-addon-api/test/build/Release/binding.node]
8: 0x104c066db Napi::FunctionReference::Call(napi_value__*, std::initializer_list<napi_value__*> const&) const [/Users/rolftimmermans/Code/vendor/node-addon-api/test/build/Release/binding.node]
9: 0x104c06e42 Napi::AsyncWorker::OnError(Napi::Error const&) [/Users/rolftimmermans/Code/vendor/node-addon-api/test/build/Release/binding.node]
10: 0x104c05d59 Napi::AsyncWorker::OnWorkComplete(napi_env__*, napi_status, void*)::'lambda'()::operator()() const [/Users/rolftimmermans/Code/vendor/node-addon-api/test/build/Release/binding.node]
11: 0x104c04191 Napi::AsyncWorker::OnWorkComplete(napi_env__*, napi_status, void*) [/Users/rolftimmermans/Code/vendor/node-addon-api/test/build/Release/binding.node]
12: 0x100061e1d (anonymous namespace)::uvimpl::Work::AfterThreadPoolWork(int) [/usr/local/bin/node]
13: 0x100691aec uv__work_done [/usr/local/bin/node]
14: 0x100695037 uv__async_io [/usr/local/bin/node]
15: 0x1006a4426 uv__io_poll [/usr/local/bin/node]
16: 0x100695472 uv_run [/usr/local/bin/node]
17: 0x10003ddb2 node::Environment::CleanupHandles() [/usr/local/bin/node]
18: 0x10003df13 node::Environment::RunCleanup() [/usr/local/bin/node]
19: 0x1000b6f8a node::NodeMainInstance::Run() [/usr/local/bin/node]
20: 0x10005fd0c node::Start(int, char**) [/usr/local/bin/node]
21: 0x7fff6dd953d5 start [/usr/lib/system/libdyld.dylib]
[1] 32869 abort node --expose-gc test/asyncworker.js
I would expect:
- the code to remain working as is, or
- any async code to not be called anymore and the process to exit cleanly, or
- (edit) a user-friendly JS exception to be thrown
I am running into this issue with zeromq.js, where I can't control users calling into the native code from an exit hook and this leads to similar fatal errors. Maybe there could be a way to check if the process/thread is exiting from within the native code?