Skip to content

Impossible to listen to beforeExit in single-tick --eval #8534

Closed
@Fishrock123

Description

@Fishrock123
  • Version: v2.2.0+ (?)
  • Platform: all
  • Subsystem: process

The following exits without printing:

node -e "process.on('beforeExit', () => process._rawDebug('hi'))"

However, this does print:

node -e "process.on('beforeExit', () => process._rawDebug('hi')); setImmediate(()=>{})"

I did some debugging and using this patch I get the following output:

diff --git a/lib/events.js b/lib/events.js
index d676580..16ee82c 100644
--- a/lib/events.js
+++ b/lib/events.js
@@ -138,6 +138,8 @@ EventEmitter.prototype.emit = function emit(type) {
   var needDomainExit = false;
   var doError = (type === 'error');

+  // process._rawDebug((new Error()).stack)
+
   events = this._events;
   if (events)
     doError = (doError && events.error == null);
@@ -169,6 +171,9 @@ EventEmitter.prototype.emit = function emit(type) {

   handler = events[type];

+  process._rawDebug('01.5:' + type)
+  process._rawDebug(typeof handler)
+
   if (!handler)
     return false;

@@ -234,6 +239,9 @@ function _addListener(target, type, listener, prepend) {
   }

   if (!existing) {
+    process._rawDebug('@@@@')
+    // process._rawDebug((new Error()).stack)
+    // process._rawDebug(listener.toString())
     // Optimize the case of one listener. Don't need the extra array object.
     existing = events[type] = listener;
     ++target._eventsCount;
diff --git a/lib/internal/process/next_tick.js b/lib/internal/process/next_tick.js
index 529645a..5f43ba0 100644
--- a/lib/internal/process/next_tick.js
+++ b/lib/internal/process/next_tick.js
@@ -138,6 +138,8 @@ function setupNextTick() {
   }

   function nextTick(callback) {
+    process._rawDebug('#####')
+    process._rawDebug((new Error()).stack)
     if (typeof callback !== 'function')
       throw new TypeError('callback is not a function');
     // on the way out, don't bother. it won't get fired anyway.
./node -e "process.on('beforeExit', () => process._rawDebug('hi'))"
@@@@
@@@@
01.5:newListener
function
@@@@
#####
Error
    at process.nextTick (internal/process/next_tick.js:142:24)
    at evalScript (bootstrap_node.js:344:13)
    at run (bootstrap_node.js:110:11)
    at run (bootstrap_node.js:382:7)
    at startup (bootstrap_node.js:109:9)
    at bootstrap_node.js:497:3
01.5:beforeExit
undefined
01.5:newListener
function
@@@@
01.5:exit
undefined

That is, beforeExit fires before the listener is attached.

Turns out that at evalScript (bootstrap_node.js:344:13) leads to this code and comment in evalScript():

    // 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.
    process.nextTick(function() {
      const result = module._compile(script, `${name}-wrapper`);
      if (process._print_eval) console.log(result);
    });

That comment leads back to #1600 - net.listen does not emit 'listening' event when in --eval mode.

That was fixed in 93a44d5 by @bnoordhuis and reviewed by @trevnorris resulting in this code in evalScript().

Not sure how to fix this right now, but it seems like a deeper bug somewhere relating to startup and nextTick.

Refs: #1793 & #1600 & also the older nodejs/node-v0.x-archive#14168

Edit: found by @cxreg

Metadata

Metadata

Assignees

No one assigned

    Labels

    confirmed-bugIssues with confirmed bugs.processIssues and PRs related to the process subsystem.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions