Skip to content

Commit c06e2b0

Browse files
trevnorrisMyles Borins
authored and
Myles Borins
committed
async_wrap: notify post if intercepted exception
The second argument of the post callback is a boolean indicating whether the callback threw and was intercepted by uncaughtException or a domain. Currently node::MakeCallback has no way of retrieving a uid for the object. This is coming in a future patch. Ref: #7048 PR-URL: #5756 Reviewed-By: Ben Noordhuis <[email protected]> Reviewed-By: Andreas Madsen <[email protected]>
1 parent 0642a14 commit c06e2b0

File tree

3 files changed

+44
-2
lines changed

3 files changed

+44
-2
lines changed

src/async-wrap.cc

+4-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "v8-profiler.h"
1010

1111
using v8::Array;
12+
using v8::Boolean;
1213
using v8::Context;
1314
using v8::Function;
1415
using v8::FunctionCallbackInfo;
@@ -231,7 +232,9 @@ Local<Value> AsyncWrap::MakeCallback(const Local<Function> cb,
231232
Local<Value> ret = cb->Call(context, argc, argv);
232233

233234
if (ran_init_callback() && !post_fn.IsEmpty()) {
234-
if (post_fn->Call(context, 1, &uid).IsEmpty())
235+
Local<Value> did_throw = Boolean::New(env()->isolate(), ret.IsEmpty());
236+
Local<Value> vals[] = { uid, did_throw };
237+
if (post_fn->Call(context, arraysize(vals), vals).IsEmpty())
235238
FatalError("node::AsyncWrap::MakeCallback", "post hook threw");
236239
}
237240

src/node.cc

+6-1
Original file line numberDiff line numberDiff line change
@@ -1172,7 +1172,12 @@ Local<Value> MakeCallback(Environment* env,
11721172
Local<Value> ret = callback->Call(recv, argc, argv);
11731173

11741174
if (ran_init_callback && !post_fn.IsEmpty()) {
1175-
if (post_fn->Call(object, 0, nullptr).IsEmpty())
1175+
Local<Value> did_throw = Boolean::New(env->isolate(), ret.IsEmpty());
1176+
// Currently there's no way to retrieve an uid from node::MakeCallback().
1177+
// This needs to be fixed.
1178+
Local<Value> vals[] =
1179+
{ Undefined(env->isolate()).As<Value>(), did_throw };
1180+
if (post_fn->Call(object, arraysize(vals), vals).IsEmpty())
11761181
FatalError("node::MakeCallback", "post hook threw");
11771182
}
11781183

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
'use strict';
2+
3+
require('../common');
4+
const assert = require('assert');
5+
const async_wrap = process.binding('async_wrap');
6+
var asyncThrows = 0;
7+
var uncaughtExceptionCount = 0;
8+
9+
process.on('uncaughtException', (e) => {
10+
assert.equal(e.message, 'oh noes!', 'error messages do not match');
11+
});
12+
13+
process.on('exit', () => {
14+
process.removeAllListeners('uncaughtException');
15+
assert.equal(uncaughtExceptionCount, 1);
16+
assert.equal(uncaughtExceptionCount, asyncThrows);
17+
});
18+
19+
function init() { }
20+
function post(id, threw) {
21+
if (threw)
22+
uncaughtExceptionCount++;
23+
}
24+
25+
async_wrap.setupHooks({ init, post });
26+
async_wrap.enable();
27+
28+
// Timers still aren't supported, so use crypto API.
29+
// It's also important that the callback not happen in a nextTick, like many
30+
// error events in core.
31+
require('crypto').randomBytes(0, () => {
32+
asyncThrows++;
33+
throw new Error('oh noes!');
34+
});

0 commit comments

Comments
 (0)