You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
$ make
v14.15.4
force gc
fish: 'node --expose_gc index.js' terminated by signal SIGSEGV (Address boundary error)
How often does it reproduce? Is there a required condition?
Always.
What is the expected behavior?
No segment faults.
What do you see instead?
Segment faults on double free of v8impl::<anonymous>::RefBase. The RefBases were deleted once one module's napi_env was going to destroy, and the installed weak v8impl::Persistents of v8impl::<anonymous>Reference was not destroyed and these RefBase will be deleted again on finalization callbacks.
@legendecas the assumption is that once the environment begins the process of being torn down, no more gc runs will happen. This test AFAICT forces gc runs after napi_env teardown, so it is entirely possible that finalizers will be called after napi_env's FinalizeAll. TBH the scenario created in the test seems unlikely to happen under normal circumstances. OTOH, it would of course be ideal to handle even unusual circumstances. Nevertheless, please be careful to not re-introduce the problem fixed in c822ba7!
@gabrielschulhof we just identified the problem in random CI failures on our system. The force GC in the repro is to ensure the reproduce is reliable to show how the problem happens in the case. The crashes do happens in a low rate, but I have to say it's not unlikely to happen: in our internal tests the ratio is roughly 1/6 to crash on exit.
@gabrielschulhof Yeah, you're right. I found I've been mistaken on the repro. In the reproduction, there are strong references to the object, this is not the case I was intended to show in the first place. After reading #37303 and tried the PR on my internal case and it does crash regardlessly, I discovered that my original crash on double free of v8impl::reference is not caused by strong references but weak references. These references were set weak before the process going to exit - there is a uv ref on the corresponding handle so only after the set weak the process is going to exit. I'll double-check the re-production to make a reliable reproduction on weak references.
Activity
gabrielschulhof commentedon Feb 8, 2021
@legendecas the assumption is that once the environment begins the process of being torn down, no more gc runs will happen. This test AFAICT forces gc runs after
napi_envteardown, so it is entirely possible that finalizers will be called afternapi_env'sFinalizeAll. TBH the scenario created in the test seems unlikely to happen under normal circumstances. OTOH, it would of course be ideal to handle even unusual circumstances. Nevertheless, please be careful to not re-introduce the problem fixed in c822ba7!RaisinTen commentedon Feb 9, 2021
Is this related: #36868?
legendecas commentedon Feb 9, 2021
@gabrielschulhof we just identified the problem in random CI failures on our system. The force GC in the repro is to ensure the reproduce is reliable to show how the problem happens in the case. The crashes do happens in a low rate, but I have to say it's not unlikely to happen: in our internal tests the ratio is roughly 1/6 to crash on exit.
legendecas commentedon Feb 9, 2021
Yes, the crash call stacks seem very similar to the case. I strongly believe it's the same problem.
gabrielschulhof commentedon Feb 9, 2021
@legendecas I ran the repro and it dies reliably even without
--expose-gc.gabrielschulhof commentedon Feb 9, 2021
@legendecas
seems to avert the problem without breaking the tests.
gabrielschulhof commentedon Feb 10, 2021
@legendecas in your repro you delete
wrapper_in two places:https://github.com/legendecas/repro-napi-v8impl-refbase-double-free/blob/5b0ae1874b9b26fb0fe453565484a004801c70e4/test.cc#L56
napi_wrapfinalizer (which calls~MyObject)https://github.com/legendecas/repro-napi-v8impl-refbase-double-free/blob/5b0ae1874b9b26fb0fe453565484a004801c70e4/test.cc#L27
So, it looks like the double free is not really caused by anything Node-API does wrong.
gabrielschulhof commentedon Feb 10, 2021
NM. Looks like it crashes even if I remove the
napi_delete_referencefrom the instance finalizer.gabrielschulhof commentedon Feb 10, 2021
@legendecas I have been able to reduce the test case to legendecas/repro-napi-v8impl-refbase-double-free#1 while still retaining the crash.
gabrielschulhof commentedon Feb 10, 2021
I think the key is the
napi_reference_refit performs on the reference returned fromnapi_wrap.legendecas commentedon Feb 18, 2021
@gabrielschulhof Yeah, you're right. I found I've been mistaken on the repro. In the reproduction, there are strong references to the object, this is not the case I was intended to show in the first place. After reading #37303 and tried the PR on my internal case and it does crash regardlessly, I discovered that my original crash on double free of v8impl::reference is not caused by strong references but weak references. These references were set weak before the process going to exit - there is a uv ref on the corresponding handle so only after the set weak the process is going to exit. I'll double-check the re-production to make a reliable reproduction on weak references.
22 remaining items
node-api: stop ref gc during environment teardown
node-api: force env shutdown deferring behavior
node-api: stop ref gc during environment teardown
node-api: force env shutdown deferring behavior
node-api: stop ref gc during environment teardown
yisibl commentedon Mar 17, 2022
Has the patch for this issue been merged into Node.js 12.x?
I'm getting a
segmentation faulterror in Node.js 12, is it related to this issue? See yisibl/svg-sprite#3node-api: force env shutdown deferring behavior
node-api: stop ref gc during environment teardown
node-api: force env shutdown deferring behavior
node-api: stop ref gc during environment teardown
fix(alpine): add --runInBand workaround for N-API musl crash
node-api: force env shutdown deferring behavior
node-api: stop ref gc during environment teardown