mbostock / rw

Now stdin and stdout are files.
Other
117 stars 4 forks source link

Error: EAGAIN, resource temporarily unavailable #3

Closed shellscape closed 10 years ago

shellscape commented 10 years ago

Running on Mac OSX Mavericks, Node 0.10.4.

rw.readSync('/dev/stdin', 'utf8');

Error: EAGAIN, resource temporarily unavailable at Object.fs.readSync (fs.js:476:19)

mbostock commented 10 years ago

Ran make test. Unable to reproduce. Insufficient information to investigate.

shellscape commented 10 years ago

So standard practice in this project is to close an issue without asking for more information? Got it. If you'd like user contribution, you might try not being so quick on the trigger.

mbostock commented 10 years ago

Standard practice is to resolve issues when there’s nothing more I can do. If you want to provide more information, I can investigate and will reopen the bug.

jasondavies commented 10 years ago

A few notes:

A possible solution would be to catch EAGAIN and reattempt a few times before closing the file descriptor, similar to node-graceful-fs. You might want to try this patch and see if that works.

shellscape commented 10 years ago

@jasondavies thanks for the follow up. I'll give those possible solutions a shot this week.

jasondavies commented 10 years ago

For posterity: I managed to reproduce this using the REPL, but reading from stdin in the REPL is not sensible so there’s nothing to fix here.

> var rw = require("rw");
> rw.readFileSync("/dev/stdin", "utf8");
Error: EAGAIN, resource temporarily unavailable
    at Object.fs.readSync (fs.js:481:19)
    at Object.module.exports [as readFileSync] (/Users/jason/src/rw/lib/rw/read-file-sync.js:15:28)
    at repl:1:4
    at REPLServer.self.eval (repl.js:110:21)
    at repl.js:249:20
    at REPLServer.self.eval (repl.js:122:7)
    at Interface.<anonymous> (repl.js:239:12)
    at Interface.emit (events.js:95:17)
    at Interface._onLine (readline.js:202:10)
    at Interface._line (readline.js:531:8)
mbostock commented 10 years ago

This is a trivial way to reproduce the error. Given the following program, test-eagain:

#!/usr/bin/env node

process.stdin.pause();

console.log(rw.readFileSync("/dev/stdin", "utf8"));

Run like so:

./test-eagain

Outputs:

/Users/mbostock/Development/rw/lib/rw/read-file-sync.js:18
        throw e;
              ^
Error: EAGAIN, resource temporarily unavailable
    at Object.fs.readSync (fs.js:481:19)
    at Object.module.exports [as readFileSync] (/Users/mbostock/Development/rw/lib/rw/read-file-sync.js:14:28)
    at Object.<anonymous> (/Users/mbostock/Development/rw/test-eagain:7:16)
    at Module._compile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Function.Module.runMain (module.js:497:10)
    at startup (node.js:119:16)
    at node.js:906:3

Note that if you redirect some output to the program, rather than having it read from the TTY, you do not get an error. For example:

echo hello | ./test-eagain

Outputs:

hello

This behavior is identical to fs.readFileSync.

Interestingly, calling resume does not seem to undo the effect of calling pause. So, the following waits for TTY input as expected:

#!/usr/bin/env node

var rw = require("./");

console.log(rw.readFileSync("/dev/stdin", "utf8"));

While the following throws the EAGAIN error:

#!/usr/bin/env node

var rw = require("./");

process.stdin.pause();
process.stdin.resume(); // Doesn’t help?

console.log(rw.readFileSync("/dev/stdin", "utf8"));

I’m not really sure what’s going on here. I’d guess you aren’t allowed to pause stdin and then subsequently try to read stdin (regardless of whether you call resume)…

mbostock commented 8 years ago

In Node 5.5, using console.warn breaks rw.writeFileSync to /dev/stdout with EAGAIN, even though console.warn should only write to process.stderr.

Replacing console.warn("foo") with process.stderr.write("foo\n") seems to fix the problem. I don’t think there’s a way to fix that in this library, though.

mschwartz commented 8 years ago

EAGAIN is not handled in write-file-sync.js, so this bug will appear under various situations.

I see it in WebStorm while running the app under the debugger while trying to write to /dev/stdout.

mbostock commented 8 years ago

@mschwartz I’d love to be wrong here, but I don’t think it’s possible for rw.writeFileSync to handle EAGAIN because rw.writeFileSync is synchronous: there’s no way to wait for process.stderr or process.stdout to be ready again.

mschwartz commented 8 years ago

You are looping to write the data in chunks. You test for EPIPE and break. No harm in adding the test for EAGAIN, IMO

On Fri, Jun 17, 2016 at 10:21 AM Mike Bostock notifications@github.com wrote:

@mschwartz https://github.com/mschwartz I’d love to be wrong here, but I don’t think it’s possible for rw.writeFileSync to handle EAGAIN because rw.writeFileSync is synchronous: there’s no way to wait for process.stderr or process.stdout to be ready again.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/mbostock/rw/issues/3#issuecomment-226829143, or mute the thread https://github.com/notifications/unsubscribe/AAUHpUtsG3qCr9jGdQJZA8fI19BLZDlLks5qMteVgaJpZM4CFMse .