diff --git a/src/node.cc b/src/node.cc index a7800f8b4c54fd..d3e7d1983ceade 100644 --- a/src/node.cc +++ b/src/node.cc @@ -3961,18 +3961,26 @@ static void StartNodeInstance(void* arg) { { SealHandleScope seal(isolate); bool more; + uv_loop_t* event_loop = env->event_loop(); + do { v8::platform::PumpMessageLoop(default_platform, isolate); - more = uv_run(env->event_loop(), UV_RUN_ONCE); + more = uv_run(event_loop, UV_RUN_ONCE); if (more == false) { v8::platform::PumpMessageLoop(default_platform, isolate); EmitBeforeExit(env); + // If there are only unrefed handles left, we need to run an + // extra event loop turn to purge the unrefed handles. + if (event_loop->active_handles == 0 && + event_loop->handle_queue[0] != event_loop->handle_queue[1]) + uv_run(event_loop, UV_RUN_NOWAIT); + // Emit `beforeExit` if the loop became alive either after emitting // event, or after running some callbacks. - more = uv_loop_alive(env->event_loop()); - if (uv_run(env->event_loop(), UV_RUN_NOWAIT) != 0) + more = uv_loop_alive(event_loop); + if (uv_run(event_loop, UV_RUN_NOWAIT) != 0) more = true; } } while (more == true); diff --git a/test/parallel/test-beforeexit-event.js b/test/parallel/test-beforeexit-event.js index f3bd127b408b08..3502a1119c5501 100644 --- a/test/parallel/test-beforeexit-event.js +++ b/test/parallel/test-beforeexit-event.js @@ -1,6 +1,6 @@ 'use strict'; var assert = require('assert'); -var net = require('net'); +var fs = require('fs'); var util = require('util'); var common = require('../common'); var revivals = 0; @@ -23,18 +23,18 @@ function tryTimer() { setTimeout(function() { console.log('timeout cb, do another once beforeExit'); revivals++; - process.once('beforeExit', tryListen); + process.once('beforeExit', tryFile); }, 1); } -function tryListen() { - console.log('create a server'); - net.createServer() - .listen(common.PORT) - .on('listening', function() { - revivals++; - this.close(); - }); +function tryFile() { + console.log('open a file'); + fs.open(__filename, 'r', (err, fd) => { + if (err) throw err; + + revivals++; + fs.closeSync(fd); + }); } process.on('exit', function() { diff --git a/test/parallel/test-timers-unrefed-in-beforeexit.js b/test/parallel/test-timers-unrefed-in-beforeexit.js new file mode 100644 index 00000000000000..0ac3311816fb4d --- /dev/null +++ b/test/parallel/test-timers-unrefed-in-beforeexit.js @@ -0,0 +1,20 @@ +'use strict'; + +require('../common'); +const assert = require('assert'); + +var once = 0; + +process.on('beforeExit', () => { + if (once > 1) + throw new RangeError('beforeExit should only have been called once!'); + + setTimeout(() => {}, 1).unref(); + once++; +}); + +process.on('exit', (code) => { + if (code !== 0) return; + + assert.strictEqual(once, 1); +});