Skip to content
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

src: fix a crashing issue in Error::ThrowAsJavaScriptException via NODE_API_SWALLOW_UNTHROWABLE_EXCEPTIONS #975

Closed

Conversation

KevinEady
Copy link
Contributor

When terminating an environment (e.g., by calling worker.terminate), napi_throw, which is called by Error::ThrowAsJavaScriptException, returns napi_pending_exception, which is then incorrectly treated as a fatal error resulting in a crash. In order to not terminate the Node process, define the preprocessor directive NODE_API_SWALLOW_UNTHROWABLE_EXCEPTIONS.

rudolftam and others added 2 commits April 22, 2021 20:32
When terminating an environment (e.g., by calling worker.terminate),
napi_throw, which is called by Error::ThrowAsJavaScriptException,
returns napi_pending_exception, which is then incorrectly treated as
a fatal error resulting in a crash.
Introduce the compile option `NODE_API_SWALLOW_UNTHROWABLE_EXCEPTIONS`
to dictate fix for crashing behavior.
napi-inl.h Outdated
if (status == napi_pending_exception) {
// The environment could be terminating.
return;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this block should be added here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed.

common.gypi Outdated
@@ -15,6 +15,7 @@
}
}]
],
'defines': [ 'NODE_API_SWALLOW_UNTHROWABLE_EXCEPTIONS' ],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should not be here by default right ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @mhdawson ,

So this relates to my comment on #902 (comment) where:

Not having the define in binding.gyp and using #define prior to #include <napi.h>: I was not able to opt-in.

You can see in commit a089697 the change to move the setting from binding.gyp to #define and now all of the builds fail.

I do not think it is possible to have a per-compilation unit setting for this feature, because the Error::ThrowAsJavaScriptException is a compiled, exported symbol:

➜  test git:(swallow-unthrowable-exceptions) ✗ nm -C build/Release/binding_noexcept.node | grep ThrowAsJavaScriptException
00000000000024f0 t Napi::Error::ThrowAsJavaScriptException() const

So, when the first compilation unit uses it, it will be compiled with whatever preprocessor definitions are currently in scope.

@KevinEady KevinEady force-pushed the swallow-unthrowable-exceptions branch from cd7d47d to 3ca4de5 Compare April 23, 2021 08:44
- Move define to src
- Correct fix implementation
@KevinEady KevinEady force-pushed the swallow-unthrowable-exceptions branch from 3ca4de5 to a089697 Compare April 23, 2021 08:46
@KevinEady KevinEady force-pushed the swallow-unthrowable-exceptions branch from 7ce3576 to 3f291f7 Compare April 27, 2021 16:28
@KevinEady KevinEady marked this pull request as ready for review April 27, 2021 17:16
@KevinEady
Copy link
Contributor Author

Hi @mhdawson and team. This PR is ready for review. As discussed in last week's meeting, the last commit contains (1) the implementation change and (2) creation of new test target. Just struggling with the CI.

@KevinEady
Copy link
Contributor Author

@legendecas I believe you are working on build system changes. Since this introduces new target, will possibly need to collaborate between the two PRs.

@mhdawson
Copy link
Member

@KevinEady, if the build changes were to refactor the testing so that it is easier to add a new config that we run the tests under, unless I'm remembering wrong, I think I already landed that.

@KevinEady
Copy link
Contributor Author

@KevinEady, if the build changes were to refactor the testing so that it is easier to add a new config that we run the tests under, unless I'm remembering wrong, I think I already landed that.

Hi @mhdawson , no the build changes were to create a new target that only compiles the single file with the NODE_API_SWALLOW_UNTHROWABLE_EXCEPTIONS define.

@mhdawson
Copy link
Member

@KevinEady got it.

@mhdawson
Copy link
Member

@KevinEady I'm wondering if this is still waiting on the other PR mentioned or if its ready to go?

@KevinEady
Copy link
Contributor Author

Hi @mhdawson ,

This PR is ready to go and indeed addresses the issue in #902. I am wondering though if there is any real-world code that we can see if this fix actually solves the problem, cc: @rudolftam ?

Thanks, Kevin

Copy link
Member

@mhdawson mhdawson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@mhdawson
Copy link
Member

I'll just hold off landing this until the 4.0 release goes out.

@mhdawson
Copy link
Member

Actually thinking about it, I don't see the harm of it being in 4.x so landing now.

mhdawson pushed a commit that referenced this pull request Jun 14, 2021
When terminating an environment (e.g., by calling worker.terminate),
napi_throw, which is called by Error::ThrowAsJavaScriptException,
returns napi_pending_exception, which is then incorrectly treated as
a fatal error resulting in a crash.

PR-URL: #975
Reviewed-By: Nicola Del Gobbo <[email protected]>
Reviewed-By: Gabriel Schulhof <[email protected]>
Reviewed-By: Chengzhong Wu <[email protected]>
Reviewed-By: Michael Dawson <[email protected]>
@mhdawson
Copy link
Member

Landed as 028107f

@mhdawson mhdawson closed this Jun 14, 2021
@mhdawson
Copy link
Member

@KevinEady I've landed but I am wondering about testing with the additional define. Should I see additional output when I run npm test or is that all hidden behind the scenes and I should only see one line for each test?

@KevinEady
Copy link
Contributor Author

Hi @mhdawson ,

There are two additional build targets (1, 2) and one test (1) that runs everything in the background via a separate node process:

switch (index_for_test_case) {
case 0:
binding.error.throwJSError('test', true);
break;
case 1:
binding.error.throwTypeError('test', true);
break;
case 2:
binding.error.throwRangeError('test', true);
break;
case 3:
binding.error.throwDefaultError(false, true);
break;
case 4:
binding.error.throwDefaultError(true, true);
break;
default: assert.fail('Invalid index');
}

@ghost
Copy link

ghost commented Jun 19, 2021

@KevinEady re: I am wondering though if there is any real-world code that we can see if this fix actually solves the problem

It was in one of my unreleased hobby projects in which I ran into this issue. It uses Node.js as an embedded library to provide scripting support for the end-user. As the scripts must be terminable (mainly for the same reasons as in web browsers), everything around them must be capable of handling it without crashing.

I'm glad that this is now possible when using node-addon-api. I'm worried, though, that the opt-in nature of this fix will mean that most addons will needlessly keep crashing in the future as well.

while (true) {
	console.log(`I hope you're not planning on terminating me. :)`)
	
	do_something_with_addon_a_fix_enabled()
	do_something_with_addon_b_fix_disabled()
	do_something_with_addon_c_fix_disabled()
	do_something_with_addon_d_fix_disabled()
}

deepakrkris pushed a commit to deepakrkris/node-addon-api that referenced this pull request Sep 23, 2021
When terminating an environment (e.g., by calling worker.terminate),
napi_throw, which is called by Error::ThrowAsJavaScriptException,
returns napi_pending_exception, which is then incorrectly treated as
a fatal error resulting in a crash.

PR-URL: nodejs#975
Reviewed-By: Nicola Del Gobbo <[email protected]>
Reviewed-By: Gabriel Schulhof <[email protected]>
Reviewed-By: Chengzhong Wu <[email protected]>
Reviewed-By: Michael Dawson <[email protected]>
deepakrkris pushed a commit to deepakrkris/node-addon-api that referenced this pull request Oct 15, 2021
When terminating an environment (e.g., by calling worker.terminate),
napi_throw, which is called by Error::ThrowAsJavaScriptException,
returns napi_pending_exception, which is then incorrectly treated as
a fatal error resulting in a crash.

PR-URL: nodejs#975
Reviewed-By: Nicola Del Gobbo <[email protected]>
Reviewed-By: Gabriel Schulhof <[email protected]>
Reviewed-By: Chengzhong Wu <[email protected]>
Reviewed-By: Michael Dawson <[email protected]>
kevindavies8 added a commit to kevindavies8/node-addon-api-Develop that referenced this pull request Aug 24, 2022
When terminating an environment (e.g., by calling worker.terminate),
napi_throw, which is called by Error::ThrowAsJavaScriptException,
returns napi_pending_exception, which is then incorrectly treated as
a fatal error resulting in a crash.

PR-URL: nodejs/node-addon-api#975
Reviewed-By: Nicola Del Gobbo <[email protected]>
Reviewed-By: Gabriel Schulhof <[email protected]>
Reviewed-By: Chengzhong Wu <[email protected]>
Reviewed-By: Michael Dawson <[email protected]>
Marlyfleitas added a commit to Marlyfleitas/node-api-addon-Development that referenced this pull request Aug 26, 2022
When terminating an environment (e.g., by calling worker.terminate),
napi_throw, which is called by Error::ThrowAsJavaScriptException,
returns napi_pending_exception, which is then incorrectly treated as
a fatal error resulting in a crash.

PR-URL: nodejs/node-addon-api#975
Reviewed-By: Nicola Del Gobbo <[email protected]>
Reviewed-By: Gabriel Schulhof <[email protected]>
Reviewed-By: Chengzhong Wu <[email protected]>
Reviewed-By: Michael Dawson <[email protected]>
wroy7860 added a commit to wroy7860/addon-api-benchmark-node that referenced this pull request Sep 19, 2022
When terminating an environment (e.g., by calling worker.terminate),
napi_throw, which is called by Error::ThrowAsJavaScriptException,
returns napi_pending_exception, which is then incorrectly treated as
a fatal error resulting in a crash.

PR-URL: nodejs/node-addon-api#975
Reviewed-By: Nicola Del Gobbo <[email protected]>
Reviewed-By: Gabriel Schulhof <[email protected]>
Reviewed-By: Chengzhong Wu <[email protected]>
Reviewed-By: Michael Dawson <[email protected]>
johnfrench3 pushed a commit to johnfrench3/node-addon-api-git that referenced this pull request Aug 11, 2023
When terminating an environment (e.g., by calling worker.terminate),
napi_throw, which is called by Error::ThrowAsJavaScriptException,
returns napi_pending_exception, which is then incorrectly treated as
a fatal error resulting in a crash.

PR-URL: nodejs/node-addon-api#975
Reviewed-By: Nicola Del Gobbo <[email protected]>
Reviewed-By: Gabriel Schulhof <[email protected]>
Reviewed-By: Chengzhong Wu <[email protected]>
Reviewed-By: Michael Dawson <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants