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

n-api: run all finalizers via SetImmediate() #34386

Conversation

gabrielschulhof
Copy link
Contributor

Checklist
  • make -j4 test (UNIX), or vcbuild test (Windows) passes
  • tests and/or benchmarks are included
  • commit message follows commit guidelines

@nodejs-github-bot nodejs-github-bot added c++ Issues and PRs that require attention from people who are familiar with C++. node-api Issues and PRs related to the Node-API. labels Jul 15, 2020
@gabrielschulhof
Copy link
Contributor Author

@addaleax this changes the gc-tests like test/js-native-api/test_reference significantly, because it involves another iteration of the event loop.

@gabrielschulhof
Copy link
Contributor Author

For testing the finalizers we need to move from a model where you

  1. set up the test,
  2. run the gc,
  3. check for expected values

to one where you

  1. set up the test,
  2. keep running the gc until the expected values appear (with a timeout after which you give up and declare the test failed)

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

@gabrielschulhof
Copy link
Contributor Author

@addaleax @mhdawson thanks for reviewing! I moved the test from test_reference to test_exception which already had a similar test, and I updated all other tests involving gc to await the changes expected in response to the gc instead of asserting that they happened. This means that the tests will time out and fail if the effects of the gc are not as expected instead of failing at an assertion.

PTAL!

// To assuage the linter's concerns.
(function() {})(x);
}
testFinalize('createExternal');
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This test is moved to its own file (testFinalizerException.js), below.

@Flarna
Copy link
Member

Flarna commented Jul 17, 2020

Could you please add a little more info in commit message which async hooks error this fixes?

@gabrielschulhof
Copy link
Contributor Author

@Flarna I squashed the commits and elaborated in the commit message on the error that is being fixed.

@gabrielschulhof gabrielschulhof changed the title Track down async hooks error n-api: run all finalizers via SetImmediate() Jul 18, 2020
@nodejs-github-bot
Copy link
Collaborator

@addaleax addaleax added the author ready PRs that have at least one approval, no pending requests for changes, and a CI started. label Jul 20, 2020
@nodejs-github-bot
Copy link
Collaborator

@nodejs-github-bot
Copy link
Collaborator

@nodejs-github-bot
Copy link
Collaborator

@gabrielschulhof
Copy link
Contributor Author

Oh, boy! Looks like I'd better drop that second commit and make it a separate PR 😳

@gabrielschulhof gabrielschulhof force-pushed the track-down-async-hooks-error branch 2 times, most recently from 17c555a to 19793e5 Compare July 22, 2020 18:15
@gabrielschulhof
Copy link
Contributor Author

Re-wrote the napi/ref benchmark to be async because it was running synchronously and so the SetImmediates never had a chance to delete the refs.

@nodejs-github-bot
Copy link
Collaborator

@gabrielschulhof
Copy link
Contributor Author

Fixed the linting.

Throwing an exception from a finalizer can cause the following fatal
error:

Error: async hook stack has become corrupted (actual: 2, expected: 0)
 1: 0x970b5a node::InternalCallbackScope::~InternalCallbackScope() [./node]
 2: 0x99dda0 node::Environment::RunTimers(uv_timer_s*) [./node]
 3: 0x13d8b22  [./node]
 4: 0x13dbe42 uv_run [./node]
 5: 0xa57974 node::NodeMainInstance::Run() [./node]
 6: 0x9dbc17 node::Start(int, char**) [./node]
 7: 0x7f4965417f43 __libc_start_main [/lib64/libc.so.6]
 8: 0x96f4ae _start [./node]

By nodejs#34341 (comment),
calling into JS from a finalizer and/or throwing exceptions from there
is not advised, because the stack may or may not be set up for JS
execution. The best solution is to run the user's finalizer from a
`SetImmediate()` callback.

Signed-off-by: Gabriel Schulhof <[email protected]>
Fixes: nodejs#34341
@gabrielschulhof
Copy link
Contributor Author

Used assert.match() to get a better idea as to why the test is failing.

@nodejs-github-bot
Copy link
Collaborator

@nodejs-github-bot
Copy link
Collaborator

@nodejs-github-bot
Copy link
Collaborator

@nodejs-github-bot
Copy link
Collaborator

gabrielschulhof pushed a commit that referenced this pull request Jul 24, 2020
Throwing an exception from a finalizer can cause the following fatal
error:

Error: async hook stack has become corrupted (actual: 2, expected: 0)
 1: 0x970b5a node::InternalCallbackScope::~InternalCallbackScope()
    [./node]
 2: 0x99dda0 node::Environment::RunTimers(uv_timer_s*) [./node]
 3: 0x13d8b22  [./node]
 4: 0x13dbe42 uv_run [./node]
 5: 0xa57974 node::NodeMainInstance::Run() [./node]
 6: 0x9dbc17 node::Start(int, char**) [./node]
 7: 0x7f4965417f43 __libc_start_main [/lib64/libc.so.6]
 8: 0x96f4ae _start [./node]

By #34341 (comment),
calling into JS from a finalizer and/or throwing exceptions from there
is not advised, because the stack may or may not be set up for JS
execution. The best solution is to run the user's finalizer from a
`SetImmediate()` callback.

Signed-off-by: Gabriel Schulhof <[email protected]>
Fixes: #34341
PR-URL: #34386
Reviewed-By: James M Snell <[email protected]>
Reviewed-By: Anna Henningsen <[email protected]>
Reviewed-By: Michael Dawson <[email protected]>
Reviewed-By: Juan José Arboleda <[email protected]>
@gabrielschulhof
Copy link
Contributor Author

Landed in a74a6e3.

@gabrielschulhof gabrielschulhof deleted the track-down-async-hooks-error branch July 24, 2020 06:29
MylesBorins pushed a commit that referenced this pull request Jul 27, 2020
Throwing an exception from a finalizer can cause the following fatal
error:

Error: async hook stack has become corrupted (actual: 2, expected: 0)
 1: 0x970b5a node::InternalCallbackScope::~InternalCallbackScope()
    [./node]
 2: 0x99dda0 node::Environment::RunTimers(uv_timer_s*) [./node]
 3: 0x13d8b22  [./node]
 4: 0x13dbe42 uv_run [./node]
 5: 0xa57974 node::NodeMainInstance::Run() [./node]
 6: 0x9dbc17 node::Start(int, char**) [./node]
 7: 0x7f4965417f43 __libc_start_main [/lib64/libc.so.6]
 8: 0x96f4ae _start [./node]

By #34341 (comment),
calling into JS from a finalizer and/or throwing exceptions from there
is not advised, because the stack may or may not be set up for JS
execution. The best solution is to run the user's finalizer from a
`SetImmediate()` callback.

Signed-off-by: Gabriel Schulhof <[email protected]>
Fixes: #34341
PR-URL: #34386
Reviewed-By: James M Snell <[email protected]>
Reviewed-By: Anna Henningsen <[email protected]>
Reviewed-By: Michael Dawson <[email protected]>
Reviewed-By: Juan José Arboleda <[email protected]>
@ruyadorno ruyadorno mentioned this pull request Jul 28, 2020
@SimenB
Copy link
Member

SimenB commented Aug 5, 2020

Is this the cause of #34636?

addaleax added a commit to node-ffi-napi/weak-napi that referenced this pull request Aug 5, 2020
addaleax added a commit to node-ffi-napi/ref-napi that referenced this pull request Aug 5, 2020
addaleax pushed a commit that referenced this pull request Sep 22, 2020
Throwing an exception from a finalizer can cause the following fatal
error:

Error: async hook stack has become corrupted (actual: 2, expected: 0)
 1: 0x970b5a node::InternalCallbackScope::~InternalCallbackScope()
    [./node]
 2: 0x99dda0 node::Environment::RunTimers(uv_timer_s*) [./node]
 3: 0x13d8b22  [./node]
 4: 0x13dbe42 uv_run [./node]
 5: 0xa57974 node::NodeMainInstance::Run() [./node]
 6: 0x9dbc17 node::Start(int, char**) [./node]
 7: 0x7f4965417f43 __libc_start_main [/lib64/libc.so.6]
 8: 0x96f4ae _start [./node]

By #34341 (comment),
calling into JS from a finalizer and/or throwing exceptions from there
is not advised, because the stack may or may not be set up for JS
execution. The best solution is to run the user's finalizer from a
`SetImmediate()` callback.

Signed-off-by: Gabriel Schulhof <[email protected]>
Fixes: #34341
PR-URL: #34386
Reviewed-By: James M Snell <[email protected]>
Reviewed-By: Anna Henningsen <[email protected]>
Reviewed-By: Michael Dawson <[email protected]>
Reviewed-By: Juan José Arboleda <[email protected]>
addaleax pushed a commit that referenced this pull request Sep 22, 2020
Throwing an exception from a finalizer can cause the following fatal
error:

Error: async hook stack has become corrupted (actual: 2, expected: 0)
 1: 0x970b5a node::InternalCallbackScope::~InternalCallbackScope()
    [./node]
 2: 0x99dda0 node::Environment::RunTimers(uv_timer_s*) [./node]
 3: 0x13d8b22  [./node]
 4: 0x13dbe42 uv_run [./node]
 5: 0xa57974 node::NodeMainInstance::Run() [./node]
 6: 0x9dbc17 node::Start(int, char**) [./node]
 7: 0x7f4965417f43 __libc_start_main [/lib64/libc.so.6]
 8: 0x96f4ae _start [./node]

By #34341 (comment),
calling into JS from a finalizer and/or throwing exceptions from there
is not advised, because the stack may or may not be set up for JS
execution. The best solution is to run the user's finalizer from a
`SetImmediate()` callback.

Signed-off-by: Gabriel Schulhof <[email protected]>
Fixes: #34341
PR-URL: #34386
Reviewed-By: James M Snell <[email protected]>
Reviewed-By: Anna Henningsen <[email protected]>
Reviewed-By: Michael Dawson <[email protected]>
Reviewed-By: Juan José Arboleda <[email protected]>
@codebytere codebytere mentioned this pull request Sep 28, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
author ready PRs that have at least one approval, no pending requests for changes, and a CI started. c++ Issues and PRs that require attention from people who are familiar with C++. node-api Issues and PRs related to the Node-API.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants