Skip to content

Commit 737d9b6

Browse files
committed
node,timers: fix beforeExit with unrefed timers
1 parent f5a3f44 commit 737d9b6

File tree

3 files changed

+33
-0
lines changed

3 files changed

+33
-0
lines changed

src/handle_wrap.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ class HandleWrap : public AsyncWrap {
5353
private:
5454
friend class Environment;
5555
friend void GetActiveHandles(const v8::FunctionCallbackInfo<v8::Value>&);
56+
friend bool HasUnrefedTimerHandles(Environment* env);
5657
static void OnClose(uv_handle_t* handle);
5758
ListNode<HandleWrap> handle_wrap_queue_;
5859
unsigned int flags_;

src/node.cc

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1543,6 +1543,18 @@ void GetActiveHandles(const FunctionCallbackInfo<Value>& args) {
15431543
args.GetReturnValue().Set(ary);
15441544
}
15451545

1546+
bool HasUnrefedTimerHandles(Environment* env) {
1547+
1548+
HandleScope handle_scope(env->isolate());
1549+
1550+
for (auto w : *env->handle_wrap_queue()) {
1551+
if (!w->persistent().IsEmpty() && w->flags_ & HandleWrap::kUnref)
1552+
return true;
1553+
}
1554+
1555+
return false;
1556+
}
1557+
15461558

15471559
static void Abort(const FunctionCallbackInfo<Value>& args) {
15481560
ABORT();
@@ -3969,6 +3981,11 @@ static void StartNodeInstance(void* arg) {
39693981
v8::platform::PumpMessageLoop(default_platform, isolate);
39703982
EmitBeforeExit(env);
39713983

3984+
// We need to run an extra event loop turn to purge unrefed handles.
3985+
bool unrefedTimers = HasUnrefedTimerHandles(env);
3986+
if (unrefedTimers == true)
3987+
uv_run(env->event_loop(), UV_RUN_NOWAIT);
3988+
39723989
// Emit `beforeExit` if the loop became alive either after emitting
39733990
// event, or after running some callbacks.
39743991
more = uv_loop_alive(env->event_loop());
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
require('../common');
2+
const assert = require('assert');
3+
4+
var once = 0;
5+
6+
process.on('beforeExit', () => {
7+
setTimeout(() => {}, 1).unref();
8+
once++;
9+
});
10+
11+
process.on('exit', (code) => {
12+
if (code !== 0) return;
13+
14+
assert.strictEqual(once, 1);
15+
});

0 commit comments

Comments
 (0)