Search code examples
node.jschild-processspawn

How can I flush a child process from nodejs


I invoke an executable C program from nodejs using spawn, but the C program seems not be flushed every time. Then, my node program can only output the child process' stdout when the buffer is full(4K) or the child process exit.

To simply the scenario, the two parts code should be:

invoke.js

var spawn = require("child_process").spawn;

var ps = spawn("./echo");
ps.stdout.on("data", (data) => {
    console.log(`${data}`); 
});
process.on("SIGINT", ps.kill);

echo.c

#include <stdio.h>
#include <signal.h>
#include <unistd.h>

static volatile int keep = 1;

void intHandler(int d){
    keep = 0;
}

int main(){
    signal(SIGINT, intHandler);
    int count = 0;
    while(keep) {
            printf("%d hello world!\r\n", ++count);
            sleep(1);
    }
}

How could I get the output from echo in the invoke.js synchronus? One important thing is I cannot modify the echo.c, I only have binary


Solution

  • You need to read the documentation about child processes/forks and how to pipe the child output to the parent process: https://nodejs.org/api/child_process.html#child_process_options_stdio

    • 'pipe' - equivalent to ['pipe', 'pipe', 'pipe'] (the default)
    • 'ignore' - equivalent to ['ignore', 'ignore', 'ignore']
    • 'inherit' -equivalent to [process.stdin, process.stdout, process.stderr] or [0,1,2]

    In your case, if you don't need to do something more complex with the output, you can get rid of the on.data event listener and just initialize the spawned process with the inherit option. I've modified the SIGINT event binding to be more clear that the ps.kill is invoked.

    var spawn = require('child_process').spawn;
    
    var ps = spawn('./echo', { stdio: 'inherit' });
    
    process.on('SIGINT', function (){
      console.log('sigint received');
      ps.kill();
    });