process.exit(0): output disappears?

2019-02-15 15:13发布

问题:

Emacs lisp command calling node hello.js:

(call-process "node" nil t nil "hello.js")

Two variants of hello.js:

  • hello_1.js:

    console.log('Hello world!');
    

    Output:

    Hello world!
    0
    
  • hello_2.js:

    console.log('Hello world!');
    process.exit(5);
    

    Output (no output from log statement!):

    5
    

What is the reason that process.exit(5) causes output to be suppressed?

Notes:

  • I experienced the problem in GNU Emacs 24.3.1 (i386-mingw-nt5.1.2600) of 2013-03-17 on MARVIN in combination with Node.js v0.10.18, running on Windows XP/SP3/32.

  • I tried EShell to execute the node command line: no output

  • process.exit() calls low level process.reallyExit(), which causes the problem: no output

    process.reallyExit() is implemented in C++:

    void Exit(const FunctionCallbackInfo<Value>& args) {
      HandleScope scope(node_isolate);
      exit(args[0]->IntegerValue());
    }
    

    [...]

    NODE_SET_METHOD(process, "reallyExit", Exit);
    

回答1:

Phew, I figured it out myself. First of all, I discovered that a delay causes the output to appear:

hello_3.js:

console.log('Hello world!');
setTimeout(function () {
    process.exit(5);
}, 1000);

Output:

Hello world!
5

So I double checked Node.js documentation for console, and found:

The console functions are synchronous when the destination is a terminal or a file (to avoid lost messages in case of premature exit) and asynchronous when it's a pipe (to avoid blocking for long periods of time).

Then I decided to make sure that no pipe is used and wrote a batch script hello_2.bat:

@ECHO OFF
node hello_2.js >test
TYPE test

Output when calling the script with (call-process "cmd.exe" nil t nil "/C" "hello_2.bat"):

Hello world!
0

(return value is 0 instead of 5, but I don't care about that)

To answer my question:

  1. It looks like call-process in Emacs on Windows uses a pipe for retrieving output from programs.

    As I also mentioned EShell: It does not seem to be recognized as a terminal by Node.js on Windows, and possibly EShell internally uses call-process or similar to run programs.

  2. Detection of a pipe as destination for standard output causes console.log to be run asynchronously.

  3. process.exit(5) in Node.js on Windows seems to discard all scheduled asynchronous tasks, and thus no output is generated.

    This assumption is supported by the outcome of desperately directing output to a pipe inside the Windows command prompt:

    C:\Temp> node hello_2.js | MORE
    
    C:\Temp>
    

Finally, I found out that the issue is known since about a year ago (as of September 2013).