Olian04 / gleam_stdin

This package provides a synchronous iterator for consuming stdin. It supports all the non-browser targets, Erlang, Node, Deno, and Bun.
https://hex.pm/packages/stdin
13 stars 0 forks source link

EAGAIN: resource temporarily unavailable #3

Closed lv37 closed 5 months ago

lv37 commented 5 months ago

Running the following code with Nodejs v22.2.0 throws an error

import gleam/io
import gleam/iterator.{Next}
import stdin.{stdin}

pub fn main() {
  let assert Next(line1, _) =
    stdin()
    |> iterator.step()
  io.debug(line1)

  let assert Next(line2, _) =
    stdin()
    |> iterator.step()
  io.debug(line2)
}

https://github.com/Olian04/gleam-stdin/assets/132778382/12e9e1a4-6360-46ed-a1d6-8ae026bb4691

Olian04 commented 5 months ago

I'm unable to reproduce this on Node 22.2.0. What OS are you on?

image

lv37 commented 5 months ago

I'm on Fedora Linux 40

Olian04 commented 5 months ago

I'm still failing to reproduce the issue 🤔

[oliver@fedora gleam-stdin]$ cat /etc/fedora-release
Fedora release 40 (Forty)
[oliver@fedora gleam-stdin]$ node -v
v22.2.0
[oliver@fedora gleam-stdin]$ cat ./src/stdin_test.gleam
import gleam/io
import gleam/iterator.{Next}
import stdin.{stdin}

pub fn main() {
  let assert Next(line1, _) =
    stdin()
    |> iterator.step()
  io.debug(line1)

  let assert Next(line2, _) =
    stdin()
    |> iterator.step()
  io.debug(line2)
}
[oliver@fedora gleam-stdin]$ cat README.md | ~/gleam test --target=javascript --runtime=node
   Compiled in 0.01s
    Running stdin_test.main
"[![Package Version](https://img.shields.io/hexpm/v/stdin)](https://hex.pm/packages/stdin)\n"
"[![Hex Docs](https://img.shields.io/badge/hex-docs-ffaff3)](https://hexdocs.pm/stdin/)\n"
[oliver@fedora gleam-stdin]$ cat README.md | ~/gleam test --target=javascript --runtime=bun
   Compiled in 0.01s
    Running stdin_test.main
"[![Package Version](https://img.shields.io/hexpm/v/stdin)](https://hex.pm/packages/stdin)\n"
"[![Hex Docs](https://img.shields.io/badge/hex-docs-ffaff3)](https://hexdocs.pm/stdin/)\n"
[oliver@fedora gleam-stdin]$ cat README.md | ~/gleam test --target=javascript --runtime=deno
   Compiled in 0.01s
    Running stdin_test.main
"[![Package Version](https://img.shields.io/hexpm/v/stdin)](https://hex.pm/packages/stdin)\n"
"[![Hex Docs](https://img.shields.io/badge/hex-docs-ffaff3)](https://hexdocs.pm/stdin/)\n"
[oliver@fedora gleam-stdin]$ cat README.md | ~/gleam test --target=erlang
   Compiled in 0.01s
    Running stdin_test.main
"[![Package Version](https://img.shields.io/hexpm/v/stdin)](https://hex.pm/packages/stdin)\n"
"[![Hex Docs](https://img.shields.io/badge/hex-docs-ffaff3)](https://hexdocs.pm/stdin/)\n"
[oliver@fedora gleam-stdin]$
lv37 commented 5 months ago

When piping into gleam run it works as expected. You should run it like I did in the video. image

Olian04 commented 5 months ago

Alright, I can reproduce it.

[oliver@fedora gleam-stdin]$ cat /etc/fedora-release
Fedora release 40 (Forty)
[oliver@fedora gleam-stdin]$ node -v
v22.2.0
[oliver@fedora gleam-stdin]$ cat ./src/stdin_test.gleam
import gleam/io
import gleam/iterator.{Next}
import stdin.{stdin}

pub fn main() {
  let assert Next(line1, _) =
    stdin()
    |> iterator.step()
  io.debug(line1)

  let assert Next(line2, _) =
    stdin()
    |> iterator.step()
  io.debug(line2)
}
[oliver@fedora gleam-stdin]$ ~/gleam test --target=javascript --runtime=node
   Compiled in 0.02s
    Running stdin_test.main
dddd
"dddd\n"
node:fs:752
  return binding.read(fd, buffer, offset, length, position);
                 ^

Error: EAGAIN: resource temporarily unavailable, read
    at readSync (node:fs:752:18)
    at stdinGenerator (file:///Users/oliver/Documents/private-repos/gleam-stdin/build/dev/javascript/stdin/js_ffi.mjs:35:9)
    at stdinGenerator.next (<anonymous>)
    at read_line (file:///Users/oliver/Documents/private-repos/gleam-stdin/build/dev/javascript/stdin/js_ffi.mjs:54:22)
    at read_line (file:///Users/oliver/Documents/private-repos/gleam-stdin/build/dev/javascript/stdin/stdin.mjs:9:15)
    at file:///Users/oliver/Documents/private-repos/gleam-stdin/build/dev/javascript/gleam_stdlib/gleam/iterator.mjs:103:53
    at file:///Users/oliver/Documents/private-repos/gleam-stdin/build/dev/javascript/gleam_stdlib/gleam/iterator.mjs:85:13
    at file:///Users/oliver/Documents/private-repos/gleam-stdin/build/dev/javascript/gleam_stdlib/gleam/iterator.mjs:473:13
    at Iterator.continuation (file:///Users/oliver/Documents/private-repos/gleam-stdin/build/dev/javascript/gleam_stdlib/gleam/iterator.mjs:248:13)
    at Module.step (file:///Users/oliver/Documents/private-repos/gleam-stdin/build/dev/javascript/gleam_stdlib/gleam/iterator.mjs:186:20) {
  errno: -11,
  code: 'EAGAIN',
  syscall: 'read'
}

Node.js v22.2.0

Now to debug it 😄

Edit 1:

Seems like its specifically a nodejs issue. Deno and Bun are fine.

[oliver@fedora gleam-stdin]$ ~/gleam test --target=javascript --runtime=bun
   Compiled in 0.01s
    Running stdin_test.main
gfdsa
"gfdsa\n"
dsa
"dsa\n"

gtrew
^C[oliver@fedora gleam-stdin]$ ~/gleam test --target=javascript --runtime=deno
   Compiled in 0.01s
    Running stdin_test.main
hgfds
"hgfds\n"
gfdsa
"gfdsa\n"
[oliver@fedora gleam-stdin]$

Edit 2:

Seems like its a Node issue across the Unix family. Both macOS 14 and Ubuntu 24.04 have this issue. However Windows 10 is fine.

Edit 3:

According to robertklep on SO:

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.

Olian04 commented 5 months ago

This should be fixed as of v1.1.4. Please try it out and let me know 😄

lv37 commented 5 months ago

Ok it works now. Thanks