Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
async_hooks: check for empty contexts before removing
This way we don't end up attempting to SetPromiseHooks on contexts that
have already been collected.

Fixes: #39019

PR-URL: #39095
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 Stephen Belanger committed Aug 1, 2021
commit 3e2fdff2cb2439de469de98cfa55c29b71418b58
12 changes: 11 additions & 1 deletion src/env-inl.h
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
@@ -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();