Skip to content

Commit

Permalink
async_hooks: check for empty contexts before removing
Browse files Browse the repository at this point in the history
This way we don't end up attempting to SetPromiseHooks on contexts that
have already been collected.

Fixes: #39019

PR-URL: #39095
Backport-PR-URL: #38577
Reviewed-By: Stephen Belanger <admin@stephenbelanger.com>
Reviewed-By: Gerhard Stöbich <deb2001-github@yahoo.de>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: Andrey Pechkurov <apechkurov@gmail.com>
Reviewed-By: Danielle Adams <adamzdanielle@gmail.com>
  • Loading branch information
bengl authored and MylesBorins committed Aug 31, 2021
1 parent 691c00c commit 48e5971
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 1 deletion.
12 changes: 11 additions & 1 deletion src/env-inl.h
Expand Up @@ -127,6 +127,11 @@ inline void AsyncHooks::SetJSPromiseHooks(v8::Local<v8::Function> init,
js_promise_hooks_[2].Reset(env()->isolate(), after);
js_promise_hooks_[3].Reset(env()->isolate(), resolve);
for (auto it = contexts_.begin(); it != contexts_.end(); it++) {
if (it->IsEmpty()) {
it = contexts_.erase(it);
it--;
continue;
}
PersistentToLocal::Weak(env()->isolate(), *it)
->SetPromiseHooks(init, before, after, resolve);
}
Expand Down Expand Up @@ -279,8 +284,13 @@ inline void AsyncHooks::RemoveContext(v8::Local<v8::Context> ctx) {
v8::Isolate* isolate = env()->isolate();
v8::HandleScope handle_scope(isolate);
for (auto it = contexts_.begin(); it != contexts_.end(); it++) {
if (it->IsEmpty()) {
it = contexts_.erase(it);
it--;
continue;
}
v8::Local<v8::Context> saved_context =
PersistentToLocal::Weak(env()->isolate(), *it);
PersistentToLocal::Weak(isolate, *it);
if (saved_context == ctx) {
it->Reset();
contexts_.erase(it);
Expand Down
15 changes: 15 additions & 0 deletions test/parallel/test-async-hooks-vm-gc.js
@@ -0,0 +1,15 @@
// Flags: --expose-gc
'use strict';

require('../common');
const asyncHooks = require('async_hooks');
const vm = require('vm');

// This is a regression test for https://github.com/nodejs/node/issues/39019
//
// It should not segfault.

const hook = asyncHooks.createHook({ init() {} }).enable();
vm.createContext();
globalThis.gc();
hook.disable();

0 comments on commit 48e5971

Please sign in to comment.