Browse Source

lib: fix event race condition with -e

Commit c5b07d4 ("lib: fix beforeExit not working with -e") runs the
to-be-evaluated code at a later time than before because it switches
from `process.nextTick()` to `setImmediate()`.

It affects `-e 'process.on("message", ...)'` because there is now a
larger time gap between startup and attaching the event listener,
increasing the chances of missing early messages.  I'm reasonably
sure `process.nextTick()` was also susceptible to that, only less
pronounced.

Avoid the problem altogether by evaluating the code synchronously.
Harmonizes the logic with `Module.runMain()` from lib/module.js
which also calls `process._tickCallback()` afterwards.

PR-URL: https://github.com/nodejs/node/pull/11958
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Jeremiah Senkpiel <fishrock123@rocketmail.com>
Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com>
Reviewed-By: Daijiro Wachi <daijiro.wachi@gmail.com>
v6.x
Ben Noordhuis 8 years ago
committed by Myles Borins
parent
commit
1a7d6337fb
No known key found for this signature in database GPG Key ID: 933B01F40B5CA946
  1. 6
      lib/internal/bootstrap_node.js
  2. 53
      test/message/eval_messages.out
  3. 37
      test/message/stdin_messages.out
  4. 19
      test/parallel/test-cli-eval.js

6
lib/internal/bootstrap_node.js

@ -351,13 +351,9 @@
'return require("vm").runInThisContext(' + 'return require("vm").runInThisContext(' +
`${JSON.stringify(body)}, { filename: ` + `${JSON.stringify(body)}, { filename: ` +
`${JSON.stringify(name)}, displayErrors: true });\n`; `${JSON.stringify(name)}, displayErrors: true });\n`;
// Defer evaluation for a tick. This is a workaround for deferred
// events not firing when evaluating scripts from the command line,
// see https://github.com/nodejs/node/issues/1600.
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);
}); process._tickCallback();
} }
// Load preload modules // Load preload modules

53
test/message/eval_messages.out

@ -3,14 +3,15 @@
with(this){__filename} with(this){__filename}
^^^^ ^^^^
SyntaxError: Strict mode code may not include a with statement SyntaxError: Strict mode code may not include a with statement
at createScript (vm.js:*) at createScript (vm.js:*:*)
at Object.runInThisContext (vm.js:*) at Object.runInThisContext (vm.js:*:*)
at Object.<anonymous> ([eval]-wrapper:*:*) at Object.<anonymous> ([eval]-wrapper:*:*)
at Module._compile (module.js:*:*) at Module._compile (module.js:*:*)
at Immediate.<anonymous> (bootstrap_node.js:*:*) at evalScript (bootstrap_node.js:*:*)
at runCallback (timers.js:*:*) at run (bootstrap_node.js:*:*)
at tryOnImmediate (timers.js:*:*) at run (bootstrap_node.js:*:*)
at processImmediate [as _immediateCallback] (timers.js:*:*) at startup (bootstrap_node.js:*:*)
at bootstrap_node.js:*:*
42 42
42 42
[eval]:1 [eval]:1
@ -19,28 +20,31 @@ throw new Error("hello")
Error: hello Error: hello
at [eval]:1:7 at [eval]:1:7
at ContextifyScript.Script.runInThisContext (vm.js:*) at ContextifyScript.Script.runInThisContext (vm.js:*:*)
at Object.runInThisContext (vm.js:*) at Object.runInThisContext (vm.js:*:*)
at Object.<anonymous> ([eval]-wrapper:*:*) at Object.<anonymous> ([eval]-wrapper:*:*)
at Module._compile (module.js:*:*) at Module._compile (module.js:*:*)
at Immediate.<anonymous> (bootstrap_node.js:*:*) at evalScript (bootstrap_node.js:*:*)
at runCallback (timers.js:*:*) at run (bootstrap_node.js:*:*)
at tryOnImmediate (timers.js:*:*) at run (bootstrap_node.js:*:*)
at processImmediate [as _immediateCallback] (timers.js:*:*) at startup (bootstrap_node.js:*:*)
at bootstrap_node.js:*:*
[eval]:1 [eval]:1
throw new Error("hello") throw new Error("hello")
^ ^
Error: hello Error: hello
at [eval]:1:7 at [eval]:1:7
at ContextifyScript.Script.runInThisContext (vm.js:*) at ContextifyScript.Script.runInThisContext (vm.js:*:*)
at Object.runInThisContext (vm.js:*) at Object.runInThisContext (vm.js:*:*)
at Object.<anonymous> ([eval]-wrapper:*:*) at Object.<anonymous> ([eval]-wrapper:*:*)
at Module._compile (module.js:*:*) at Module._compile (module.js:*:*)
at Immediate.<anonymous> (bootstrap_node.js:*:*) at evalScript (bootstrap_node.js:*:*)
at runCallback (timers.js:*:*) at run (bootstrap_node.js:*:*)
at tryOnImmediate (timers.js:*:*) at run (bootstrap_node.js:*:*)
at processImmediate [as _immediateCallback] (timers.js:*:*) at startup (bootstrap_node.js:*:*)
at bootstrap_node.js:*:*
100 100
[eval]:1 [eval]:1
var x = 100; y = x; var x = 100; y = x;
@ -48,14 +52,15 @@ var x = 100; y = x;
ReferenceError: y is not defined ReferenceError: y is not defined
at [eval]:1:16 at [eval]:1:16
at ContextifyScript.Script.runInThisContext (vm.js:*) at ContextifyScript.Script.runInThisContext (vm.js:*:*)
at Object.runInThisContext (vm.js:*) at Object.runInThisContext (vm.js:*:*)
at Object.<anonymous> ([eval]-wrapper:*:*) at Object.<anonymous> ([eval]-wrapper:*:*)
at Module._compile (module.js:*:*) at Module._compile (module.js:*:*)
at Immediate.<anonymous> (bootstrap_node.js:*:*) at evalScript (bootstrap_node.js:*:*)
at runCallback (timers.js:*:*) at run (bootstrap_node.js:*:*)
at tryOnImmediate (timers.js:*:*) at run (bootstrap_node.js:*:*)
at processImmediate [as _immediateCallback] (timers.js:*:*) at startup (bootstrap_node.js:*:*)
at bootstrap_node.js:*:*
[eval]:1 [eval]:1
var ______________________________________________; throw 10 var ______________________________________________; throw 10

37
test/message/stdin_messages.out

@ -7,10 +7,12 @@ SyntaxError: Strict mode code may not include a with statement
at Object.runInThisContext (vm.js:*) at Object.runInThisContext (vm.js:*)
at Object.<anonymous> ([stdin]-wrapper:*:*) at Object.<anonymous> ([stdin]-wrapper:*:*)
at Module._compile (module.js:*:*) at Module._compile (module.js:*:*)
at Immediate.<anonymous> (bootstrap_node.js:*:*) at evalScript (bootstrap_node.js:*:*)
at runCallback (timers.js:*:*) at Socket.<anonymous> (bootstrap_node.js:*:*)
at tryOnImmediate (timers.js:*:*) at emitNone (events.js:*:*)
at processImmediate [as _immediateCallback] (timers.js:*:*) at Socket.emit (events.js:*:*)
at endReadableNT (_stream_readable.js:*:*)
at _combinedTickCallback (internal/process/next_tick.js:*:*)
42 42
42 42
[stdin]:1 [stdin]:1
@ -23,10 +25,11 @@ Error: hello
at Object.runInThisContext (vm.js:*) at Object.runInThisContext (vm.js:*)
at Object.<anonymous> ([stdin]-wrapper:*:*) at Object.<anonymous> ([stdin]-wrapper:*:*)
at Module._compile (module.js:*:*) at Module._compile (module.js:*:*)
at Immediate.<anonymous> (bootstrap_node.js:*:*) at evalScript (bootstrap_node.js:*:*)
at runCallback (timers.js:*:*) at Socket.<anonymous> (bootstrap_node.js:*:*)
at tryOnImmediate (timers.js:*:*) at emitNone (events.js:*:*)
at processImmediate [as _immediateCallback] (timers.js:*:*) at Socket.emit (events.js:*:*)
at endReadableNT (_stream_readable.js:*:*)
[stdin]:1 [stdin]:1
throw new Error("hello") throw new Error("hello")
^ ^
@ -37,10 +40,11 @@ Error: hello
at Object.runInThisContext (vm.js:*) at Object.runInThisContext (vm.js:*)
at Object.<anonymous> ([stdin]-wrapper:*:*) at Object.<anonymous> ([stdin]-wrapper:*:*)
at Module._compile (module.js:*:*) at Module._compile (module.js:*:*)
at Immediate.<anonymous> (bootstrap_node.js:*:*) at evalScript (bootstrap_node.js:*:*)
at runCallback (timers.js:*:*) at Socket.<anonymous> (bootstrap_node.js:*:*)
at tryOnImmediate (timers.js:*:*) at emitNone (events.js:*:*)
at processImmediate [as _immediateCallback] (timers.js:*:*) at Socket.emit (events.js:*:*)
at endReadableNT (_stream_readable.js:*:*)
100 100
[stdin]:1 [stdin]:1
var x = 100; y = x; var x = 100; y = x;
@ -52,10 +56,11 @@ ReferenceError: y is not defined
at Object.runInThisContext (vm.js:*) at Object.runInThisContext (vm.js:*)
at Object.<anonymous> ([stdin]-wrapper:*:*) at Object.<anonymous> ([stdin]-wrapper:*:*)
at Module._compile (module.js:*:*) at Module._compile (module.js:*:*)
at Immediate.<anonymous> (bootstrap_node.js:*:*) at evalScript (bootstrap_node.js:*:*)
at runCallback (timers.js:*:*) at Socket.<anonymous> (bootstrap_node.js:*:*)
at tryOnImmediate (timers.js:*:*) at emitNone (events.js:*:*)
at processImmediate [as _immediateCallback] (timers.js:*:*) at Socket.emit (events.js:*:*)
at endReadableNT (_stream_readable.js:*:*)
[stdin]:1 [stdin]:1
var ______________________________________________; throw 10 var ______________________________________________; throw 10

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

@ -144,3 +144,22 @@ child.exec(`${nodejs} --use-strict -p process.execArgv`,
assert.strictEqual(proc.stderr, ''); assert.strictEqual(proc.stderr, '');
assert.strictEqual(proc.stdout, 'start\nbeforeExit\nexit\n'); assert.strictEqual(proc.stdout, 'start\nbeforeExit\nexit\n');
} }
// Regression test for https://github.com/nodejs/node/issues/11948.
{
const script = `
process.on('message', (message) => {
if (message === 'ping') process.send('pong');
if (message === 'exit') process.disconnect();
});
`;
const proc = child.fork('-e', [script]);
proc.on('exit', common.mustCall((exitCode, signalCode) => {
assert.strictEqual(exitCode, 0);
assert.strictEqual(signalCode, null);
}));
proc.on('message', (message) => {
if (message === 'pong') proc.send('exit');
});
proc.send('ping');
}

Loading…
Cancel
Save