bun icon indicating copy to clipboard operation
bun copied to clipboard

`Bun.stdin.stream()` not working beyond top-level `await`

Open alexlamsl opened this issue 2 years ago • 3 comments
trafficstars

What version of Bun is running?

0.3.0 --canary

What platform is your computer?

Linux 4.4.0-17763-Microsoft x86_64 x86_64

What steps can reproduce the bug?

$ cat bad.js
var line, reader = Bun.stdin.stream().getReader();
(async function() {
  while (!(line = await reader.read()).done) {
    console.log(line);
  }
  console.log('DONE', line);
})();

What is the expected behavior?

$ cat good.js
var line, reader = Bun.stdin.stream().getReader();
while (!(line = await reader.read()).done) {
  console.log(line);
}
console.log('DONE', line);

(Typed abc<Enter><Ctrl+D>)

$ bun good.js
abc
{
  value: Uint8Array(4) [ 97, 98, 99, 10 ],
  done: false
}
{
  value: Uint8Array(0) [  ],
  done: false
}
DONE {
  value: undefined,
  done: true
}

What do you see instead?

$ bun bad.js
abc
$

Additional information

Just thought I'd file a separate issue from #1604 as this isn't related to Node.js − refer to https://github.com/oven-sh/bun/issues/1604#issuecomment-1345647940 onwards for more examples of failure.

alexlamsl avatar Dec 12 '22 16:12 alexlamsl

I think this bug is that we aren't ref/unref'ing stdin correctly

Jarred-Sumner avatar Dec 13 '22 01:12 Jarred-Sumner

I think you are right:

$ cat hack.js
var timerId;

function resume() {
  timerId = setInterval(function() {}, 1e9);
}

function pause() {
  clearInterval(timerId);
}

(async function() {
  var line, reader = Bun.stdin.stream().getReader();
  resume();
  while (!(line = await reader.read()).done) {
    console.log(line);
  }
  pause();
  console.log('DONE', line);
})();

(Typed abc<Enter><Ctrl+D>)

$ bun hack.js
abc
{
  value: Uint8Array(4) [ 97, 98, 99, 10 ],
  done: false
}
{
  value: Uint8Array(0) [  ],
  done: false
}
DONE {
  value: undefined,
  done: true
}
$

So I guess the question is, where is the code responsible for Bun.stdin being ref() which somehow only works when top-level await is being performed?

alexlamsl avatar Dec 13 '22 02:12 alexlamsl

$ cat test.js
// same results with:
// var reader = Bun.file(process.stdin.fd).stream().getReader();
var reader = Bun.stdin.stream().getReader();
(async function() {
  do {
    var { done, value } = await reader.read();
    console.log(value);
  } while (!done);
  console.log("ENDED");
})();

Captures the immediately available abc, then abruptly exits (read: no ENDED) before def makes it through the pipe:

$ (echo "abc"; sleep 5; echo "def") | bun test.js
Uint8Array(4) [ 97, 98, 99, 10 ]
$ 

I wonder this issue would also reproduce over large and/or slow file data :thinking:

Edit: for completeness:

$ (echo "abc"; sleep 0; echo "def") | bun test.js
Uint8Array(8) [ 97, 98, 99, 10, 100, 101, 102, 10 ]
undefined
ENDED
$

alexlamsl avatar Dec 18 '22 21:12 alexlamsl

This has been fixed, tested as of Bun v1.0.7.

Electroid avatar Oct 25 '23 19:10 Electroid