Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Stdin read fails on some input

Tags:

node.js

stdin

#!/usr/bin/env node

function stdinReadSync() {
   var b = new Buffer(1024);
   var data = '';

   while (true) {
      var n = require('fs').readSync(process.stdin.fd, b, 0, b.length);
      if (!n) break;
      data += b.toString(null, 0, n);
   }
   return data;
}

var s = stdinReadSync();
console.log(s.length);

The above code (taken from Stackoverflow) works just fine if you feed it with echo, cat, ls, but will fail with curl output.

$ echo abc | ./test.js
4

$ ls | ./test.js
1056

$ cat 1.txt | ./test.js
78

$ curl -si wikipedia.org | ./test.js
fs.js:725
  var r = binding.read(fd, buffer, offset, length, position);
                  ^

Error: EAGAIN: resource temporarily unavailable, read
    at Error (native)
    at Object.fs.readSync (fs.js:725:19)
    at stdinReadSync (/home/ya/2up/api/stdinrd.js:8:29)
    at Object.<anonymous> (/home/ya/2up/api/stdinrd.js:15:9)
    at Module._compile (module.js:541:32)
    at Object.Module._extensions..js (module.js:550:10)
    at Module.load (module.js:456:32)
    at tryModuleLoad (module.js:415:12)
    at Function.Module._load (module.js:407:3)
    at Function.Module.runMain (module.js:575:10)
(23) Failed writing body

Why? How to fix?

like image 248
exebook Avatar asked Dec 30 '25 21:12

exebook


1 Answers

It's a bit of a hack, but this seems to work:

var n = require('fs').readSync(0, b, 0, b.length);

I think (pure conjecture) that process.stdin.fd is a getter that, when referenced, will put stdin in non-blocking mode (which is causing the error). When you use the file descriptor directly, you work around that.

like image 172
robertklep Avatar answered Jan 01 '26 13:01

robertklep