Browse Source

lib: fix beforeExit not working with -e

Commit 93a44d5 ("src: fix deferred events not working with -e") defers
evaluation of the script to the next tick.

A side effect of that change is that 'beforeExit' listeners run before
the actual script.  'beforeExit' is emitted when the event loop is
empty but process.nextTick() does not ref the event loop.

Fix that by using setImmediate().  Because it is implemented in terms
of a uv_check_t handle, it interacts with the event loop properly.

Fixes: https://github.com/nodejs/node/issues/8534
PR-URL: https://github.com/nodejs/node/pull/8821
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
v6
Ben Noordhuis 8 years ago
parent
commit
c5b07d4ec6
  1. 2
      lib/internal/bootstrap_node.js
  2. 28
      test/message/eval_messages.out
  3. 28
      test/message/stdin_messages.out
  4. 15
      test/parallel/test-cli-eval.js

2
lib/internal/bootstrap_node.js

@ -341,7 +341,7 @@
// Defer evaluation for a tick. This is a workaround for deferred // Defer evaluation for a tick. This is a workaround for deferred
// events not firing when evaluating scripts from the command line, // events not firing when evaluating scripts from the command line,
// see https://github.com/nodejs/node/issues/1600. // see https://github.com/nodejs/node/issues/1600.
process.nextTick(function() { setImmediate(function() {
const result = module._compile(script, `${name}-wrapper`); const result = module._compile(script, `${name}-wrapper`);
if (process._print_eval) console.log(result); if (process._print_eval) console.log(result);
}); });

28
test/message/eval_messages.out

@ -6,9 +6,10 @@ SyntaxError: Strict mode code may not include a with statement
at Object.exports.runInThisContext (vm.js:*) at Object.exports.runInThisContext (vm.js:*)
at Object.<anonymous> ([eval]-wrapper:*:*) at Object.<anonymous> ([eval]-wrapper:*:*)
at Module._compile (module.js:*:*) at Module._compile (module.js:*:*)
at bootstrap_node.js:*:* at Immediate.<anonymous> (bootstrap_node.js:*:*)
at _combinedTickCallback (internal/process/next_tick.js:*:*) at runCallback (timers.js:*:*)
at process._tickCallback (internal/process/next_tick.js:*:*) at tryOnImmediate (timers.js:*:*)
at processImmediate [as _immediateCallback] (timers.js:*:*)
42 42
42 42
[eval]:1 [eval]:1
@ -20,9 +21,10 @@ Error: hello
at Object.exports.runInThisContext (vm.js:*) at Object.exports.runInThisContext (vm.js:*)
at Object.<anonymous> ([eval]-wrapper:*:*) at Object.<anonymous> ([eval]-wrapper:*:*)
at Module._compile (module.js:*:*) at Module._compile (module.js:*:*)
at bootstrap_node.js:*:* at Immediate.<anonymous> (bootstrap_node.js:*:*)
at _combinedTickCallback (internal/process/next_tick.js:*:*) at runCallback (timers.js:*:*)
at process._tickCallback (internal/process/next_tick.js:*:*) at tryOnImmediate (timers.js:*:*)
at processImmediate [as _immediateCallback] (timers.js:*:*)
[eval]:1 [eval]:1
throw new Error("hello") throw new Error("hello")
^ ^
@ -32,9 +34,10 @@ Error: hello
at Object.exports.runInThisContext (vm.js:*) at Object.exports.runInThisContext (vm.js:*)
at Object.<anonymous> ([eval]-wrapper:*:*) at Object.<anonymous> ([eval]-wrapper:*:*)
at Module._compile (module.js:*:*) at Module._compile (module.js:*:*)
at bootstrap_node.js:*:* at Immediate.<anonymous> (bootstrap_node.js:*:*)
at _combinedTickCallback (internal/process/next_tick.js:*:*) at runCallback (timers.js:*:*)
at process._tickCallback (internal/process/next_tick.js:*:*) at tryOnImmediate (timers.js:*:*)
at processImmediate [as _immediateCallback] (timers.js:*:*)
100 100
[eval]:1 [eval]:1
var x = 100; y = x; var x = 100; y = x;
@ -45,9 +48,10 @@ ReferenceError: y is not defined
at Object.exports.runInThisContext (vm.js:*) at Object.exports.runInThisContext (vm.js:*)
at Object.<anonymous> ([eval]-wrapper:*:*) at Object.<anonymous> ([eval]-wrapper:*:*)
at Module._compile (module.js:*:*) at Module._compile (module.js:*:*)
at bootstrap_node.js:*:* at Immediate.<anonymous> (bootstrap_node.js:*:*)
at _combinedTickCallback (internal/process/next_tick.js:*:*) at runCallback (timers.js:*:*)
at process._tickCallback (internal/process/next_tick.js:*:*) at tryOnImmediate (timers.js:*:*)
at processImmediate [as _immediateCallback] (timers.js:*:*)
[eval]:1 [eval]:1
var ______________________________________________; throw 10 var ______________________________________________; throw 10
^ ^

28
test/message/stdin_messages.out

@ -7,9 +7,10 @@ SyntaxError: Strict mode code may not include a with statement
at Object.exports.runInThisContext (vm.js:*) at Object.exports.runInThisContext (vm.js:*)
at Object.<anonymous> ([stdin]-wrapper:*:*) at Object.<anonymous> ([stdin]-wrapper:*:*)
at Module._compile (module.js:*:*) at Module._compile (module.js:*:*)
at bootstrap_node.js:*:* at Immediate.<anonymous> (bootstrap_node.js:*:*)
at _combinedTickCallback (internal/process/next_tick.js:*:*) at runCallback (timers.js:*:*)
at process._tickCallback (internal/process/next_tick.js:*:*) at tryOnImmediate (timers.js:*:*)
at processImmediate [as _immediateCallback] (timers.js:*:*)
42 42
42 42
@ -22,9 +23,10 @@ Error: hello
at Object.exports.runInThisContext (vm.js:*) at Object.exports.runInThisContext (vm.js:*)
at Object.<anonymous> ([stdin]-wrapper:*:*) at Object.<anonymous> ([stdin]-wrapper:*:*)
at Module._compile (module.js:*:*) at Module._compile (module.js:*:*)
at bootstrap_node.js:*:* at Immediate.<anonymous> (bootstrap_node.js:*:*)
at _combinedTickCallback (internal/process/next_tick.js:*:*) at runCallback (timers.js:*:*)
at process._tickCallback (internal/process/next_tick.js:*:*) at tryOnImmediate (timers.js:*:*)
at processImmediate [as _immediateCallback] (timers.js:*:*)
[stdin]:1 [stdin]:1
throw new Error("hello") throw new Error("hello")
@ -35,9 +37,10 @@ Error: hello
at Object.exports.runInThisContext (vm.js:*) at Object.exports.runInThisContext (vm.js:*)
at Object.<anonymous> ([stdin]-wrapper:*:*) at Object.<anonymous> ([stdin]-wrapper:*:*)
at Module._compile (module.js:*:*) at Module._compile (module.js:*:*)
at bootstrap_node.js:*:* at Immediate.<anonymous> (bootstrap_node.js:*:*)
at _combinedTickCallback (internal/process/next_tick.js:*:*) at runCallback (timers.js:*:*)
at process._tickCallback (internal/process/next_tick.js:*:*) at tryOnImmediate (timers.js:*:*)
at processImmediate [as _immediateCallback] (timers.js:*:*)
100 100
[stdin]:1 [stdin]:1
@ -49,9 +52,10 @@ ReferenceError: y is not defined
at Object.exports.runInThisContext (vm.js:*) at Object.exports.runInThisContext (vm.js:*)
at Object.<anonymous> ([stdin]-wrapper:*:*) at Object.<anonymous> ([stdin]-wrapper:*:*)
at Module._compile (module.js:*:*) at Module._compile (module.js:*:*)
at bootstrap_node.js:*:* at Immediate.<anonymous> (bootstrap_node.js:*:*)
at _combinedTickCallback (internal/process/next_tick.js:*:*) at runCallback (timers.js:*:*)
at process._tickCallback (internal/process/next_tick.js:*:*) at tryOnImmediate (timers.js:*:*)
at processImmediate [as _immediateCallback] (timers.js:*:*)
[stdin]:1 [stdin]:1
var ______________________________________________; throw 10 var ______________________________________________; throw 10

15
test/parallel/test-cli-eval.js

@ -97,3 +97,18 @@ child.exec(nodejs + ` -e 'require("child_process").fork("${emptyFile}")'`,
assert.equal(stdout, ''); assert.equal(stdout, '');
assert.equal(stderr, ''); assert.equal(stderr, '');
}); });
// Regression test for https://github.com/nodejs/node/issues/8534.
{
const script = `
// console.log() can revive the event loop so we must be careful
// to write from a 'beforeExit' event listener only once.
process.once("beforeExit", () => console.log("beforeExit"));
process.on("exit", () => console.log("exit"));
console.log("start");
`;
const options = { encoding: 'utf8' };
const proc = child.spawnSync(process.execPath, ['-e', script], options);
assert.strictEqual(proc.stderr, '');
assert.strictEqual(proc.stdout, 'start\nbeforeExit\nexit\n');
}

Loading…
Cancel
Save