public
Created

Node.js does not detect process.stdout pipe closing

  • Download Gist
node-yes-simplistic.js
JavaScript
1 2 3 4 5 6
// this terminates: yes | head
// this hangs: node node-yes-simple.js | head
// per mhart, this is entirely expected
while(true) {
process.stdout.write('{"yes": "yes"}\n');
}
node-yes.js
JavaScript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
// Keep saying yes until interrupted or someone closes your output pipe:
 
var running = true;
function say_yes() {
if (running) {
process.stdout.write('{"yes": "yes"}\n');
process.nextTick(say_yes);
} else {
process.exit(0);
}
}
 
process.stdout.on('error', function(err) {
running = false;
if (err.code === 'EPIPE') {
// expected if output pipe closed, e.g. by `head`
process.exit(0);
} else {
process.stderr.write(JSON.stringify(err) + '\n');
process.exit(1);
}
});

You're starving the event loop with the infinite while.

Try this:

function writeYes() {
  process.stdout.write('{"yes": "yes"}\n');
  process.nextTick(writeYes);
}
writeYes();

(NB: The difference with the example in epipebomb is that the process there actually terminates so the events are processed after the for loop finishes - it's not infinite like the while examples here)

Updated. Thanks!

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.