Skip to content

Commit fadccba

Browse files
trevnorrisMylesBorins
authored andcommitted
async_wrap: return undefined if domain is disposed
v8::MaybeLocal::ToLocalChecked() will abort on an empty handle. AsyncWrap::MakeCallback returns an empty handle if the domain is disposed, but this should not cause the process to abort. So instead return v8::Undefined() and allow the error to be handled normally. PR-URL: #14722 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Refael Ackermann <[email protected]>
1 parent 4bf0d4e commit fadccba

File tree

2 files changed

+28
-2
lines changed

2 files changed

+28
-2
lines changed

src/async-wrap.cc

+3-2
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ using v8::String;
5454
using v8::Symbol;
5555
using v8::TryCatch;
5656
using v8::Uint32Array;
57+
using v8::Undefined;
5758
using v8::Value;
5859

5960
using AsyncHooks = node::Environment::AsyncHooks;
@@ -696,7 +697,7 @@ MaybeLocal<Value> AsyncWrap::MakeCallback(const Local<Function> cb,
696697
get_trigger_id());
697698

698699
if (!PreCallbackExecution(this, true)) {
699-
return MaybeLocal<Value>();
700+
return Undefined(env()->isolate());
700701
}
701702

702703
// Finally... Get to running the user's callback.
@@ -707,7 +708,7 @@ MaybeLocal<Value> AsyncWrap::MakeCallback(const Local<Function> cb,
707708
}
708709

709710
if (!PostCallbackExecution(this, true)) {
710-
return Local<Value>();
711+
return Undefined(env()->isolate());
711712
}
712713

713714
exec_scope.Dispose();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
'use strict';
2+
3+
const common = require('../common');
4+
const assert = require('assert');
5+
const domain = require('domain');
6+
7+
// These were picked arbitrarily and are only used to trigger arync_hooks.
8+
const JSStream = process.binding('js_stream').JSStream;
9+
const Socket = require('net').Socket;
10+
11+
const handle = new JSStream();
12+
handle.domain = domain.create();
13+
handle.domain.dispose();
14+
15+
handle.close = () => {};
16+
handle.isAlive = () => { throw new Error(); };
17+
18+
const s = new Socket({ handle });
19+
20+
// When AsyncWrap::MakeCallback() returned an empty handle the
21+
// MaybeLocal::ToLocalChecked() call caused the process to abort. By returning
22+
// v8::Undefined() it allows the error to propagate to the 'error' event.
23+
s.on('error', common.mustCall((e) => {
24+
assert.strictEqual(e.code, 'EINVAL');
25+
}));

0 commit comments

Comments
 (0)