oven-sh / bun

Incredibly fast JavaScript runtime, bundler, test runner, and package manager – all in one
https://bun.sh
Other
74.38k stars 2.78k forks source link

stdin redirection hangs on macOS #10080

Open alexkornitzer opened 7 months ago

alexkornitzer commented 7 months ago

Since Bun v1.0.31 which had the major IO rework, talking to Bun via an Erlang Port (https://www.erlang.org/doc/tutorial/c_port) has resulted in hangs on macOS. After investigation the issue appears to come from assumptions that Bun makes in its FileReader (https://github.com/oven-sh/bun/blob/main/src/bun.js/webcore/streams.zig#L3441), resulting in it setting the reader as non blocking when the file descriptor is not. This then results in a hang as the PosixBufferedReader handles reads in a non blocking way while the read syscall is blocking, thus EAGAIN is never raised.

I have used a rather forceful approach in local testing to fix the issue which just ensures the file descriptor is non blocking (using the already present but what appears to be unused function).

diff --git a/src/bun.js/webcore/streams.zig b/src/bun.js/webcore/streams.zig
index 7703efa21..201d21a83 100644
--- a/src/bun.js/webcore/streams.zig
+++ b/src/bun.js/webcore/streams.zig
@@ -3525,6 +3525,11 @@ pub const FileReader = struct {
                 if (this.nonblocking and this.file_type == .pipe) {
                     this.file_type = .nonblocking_pipe;
                 }
+
+                // ensure non blocking otherwise hangs will occur
+                if (this.nonblocking) {
+                    bun.ensureNonBlocking(fd.int());
+                }
             }

             this.fd = fd;

I have not raised a PR for this as I understand the fix might be to handle the broken assumptions for macOS builds rather than forcing the descriptor to be non blocking.

The following was used to reproduce the error:

test.js

for await (const line of console) {
  console.log(`line: ${line}`);
}

wrapper.sh

#!/usr/bin/env bash

exec &> >(./build/bun-debug ./test.js)

echo "I printed...!"

while read -r line; do echo $line; done
postnerd commented 3 months ago

I can also reproduce this behavior using Bun as the runtime for my chess engine, postbot.

Since Bun v1.0.31, the engine has stopped working with BanksiaGUI or the lichess-bot wrapper. According to the logs, it appears that stdin stops working after the first input.