Compare commits

...

1 Commits

Author SHA1 Message Date
pfg
65c3d963a7 try not treating a non-tty pipe as nonblocking 2025-05-01 18:00:12 -07:00
5 changed files with 87 additions and 27 deletions

View File

@@ -6,18 +6,18 @@ extern const jsc_llint_end: u8;
/// allocated using bun.default_allocator. when called from lldb, it is never freed.
pub export fn dumpBtjsTrace() [*:0]const u8 {
if (comptime bun.Environment.isDebug) {
return dumpBtjsTraceDebugImpl();
}
return "btjs is disabled in release builds";
}
fn dumpBtjsTraceDebugImpl() [*:0]const u8 {
var result_writer = std.ArrayList(u8).init(bun.default_allocator);
const w = result_writer.writer();
const debug_info = std.debug.getSelfDebugInfo() catch |err| {
w.print("Unable to dump stack trace: Unable to open debug info: {s}\x00", .{@errorName(err)}) catch {
var result_writer = std.ArrayList(u8).init(bun.default_allocator);
const w = result_writer.writer();
dumpBtjsTraceDebugImpl(w.any()) catch {
result_writer.deinit();
return "<oom>".ptr;
};
// remove nulls
for (result_writer.items) |*itm| if (itm.* == 0) {
itm.* = ' ';
};
// add null terminator
result_writer.append(0) catch {
result_writer.deinit();
return "<oom>".ptr;
};
@@ -25,6 +25,17 @@ fn dumpBtjsTraceDebugImpl() [*:0]const u8 {
result_writer.deinit();
return "<oom>".ptr;
}).ptr);
}
return "btjs is disabled in release builds";
}
pub fn printBtjsTrace() void {
dumpBtjsTraceDebugImpl(std.io.getStdOut().writer().any()) catch |err| std.log.info("Unable to dump stack trace: {s}", .{@errorName(err)});
}
fn dumpBtjsTraceDebugImpl(w: std.io.AnyWriter) !void {
const debug_info = std.debug.getSelfDebugInfo() catch |err| {
return w.print("Unable to dump stack trace: Unable to open debug info: {s}", .{@errorName(err)});
};
// std.log.info("jsc_llint_begin: {x}", .{@intFromPtr(&jsc_llint_begin)});
@@ -53,20 +64,6 @@ fn dumpBtjsTraceDebugImpl() [*:0]const u8 {
} else {
printLastUnwindError(&it, debug_info, w, tty_config);
}
// remove nulls
for (result_writer.items) |*itm| if (itm.* == 0) {
itm.* = ' ';
};
// add null terminator
result_writer.append(0) catch {
result_writer.deinit();
return "<oom>".ptr;
};
return @ptrCast((result_writer.toOwnedSlice() catch {
result_writer.deinit();
return "<oom>".ptr;
}).ptr);
}
fn printSourceAtAddress(debug_info: *std.debug.SelfInfo, out_stream: anytype, address: usize, tty_config: std.io.tty.Config, fp: usize) !void {

View File

@@ -129,7 +129,7 @@ pub const Lazy = union(enum) {
this.file_type = .nonblocking_pipe;
}
this.nonblocking = is_nonblocking or (this.pollable and !(file.is_atty orelse false));
this.nonblocking = is_nonblocking;
if (this.nonblocking and this.file_type == .pipe) {
this.file_type = .nonblocking_pipe;

View File

@@ -0,0 +1,38 @@
import { $ } from "bun";
import { bunExe, isWindows } from "harness";
const expected_output = `got data "line 1\\n"
✓ read at least 25ms apart
got data "setTimeout tick"
✓ read at least 25ms apart
got data "line 2\\n"
✓ read at least 25ms apart
got data "setTimeout tick"
✓ read at least 25ms apart
got data "line 3\\n"
✓ read at least 25ms apart
got data "setTimeout tick"
✓ read at least 25ms apart
got data "line 4\\n"
✓ read at least 25ms apart
got data "setTimeout tick"
✓ read at least 25ms apart
got data "line 5\\n"
✓ read at least 25ms apart
got data "setTimeout tick"
`;
test.skipIf(isWindows)("stdin data should be emitted as stdin is read", async () => {
const result = Bun.spawnSync({
cmd: ["sh", "-c", `${bunExe()} ${import.meta.dirname}/writer | ${bunExe()} ${import.meta.dirname}/reader`],
stdio: ["pipe", "pipe", "pipe"],
});
expect(result.exitCode).toBe(0);
expect(result.stdout.toString("utf-8")).toBe(expected_output);
expect(result.stderr.toString("utf-8")).toMatchInlineSnapshot(`""`);
});
test("[bun shell] stdin data should be emitted as stdin is read", async () => {
const txt = await $`${bunExe()} ${import.meta.dirname}/writer | ${bunExe()} ${import.meta.dirname}/reader`.text();
expect(txt).toBe(expected_output);
});

View File

@@ -0,0 +1,15 @@
let last_data = 0;
function onData(data) {
const this_data = Date.now();
if (last_data && this_data - last_data >= 25) {
console.log("✓ read at least 25ms apart");
}
last_data = this_data;
console.log("got data", JSON.stringify(data));
}
process.stdin.on("data", data => {
onData(data);
setTimeout(() => onData("setTimeout tick"), 30);
});
process.stdin.setEncoding("utf-8");

View File

@@ -0,0 +1,10 @@
await Bun.sleep(200);
console.log("line 1");
await Bun.sleep(200);
console.log("line 2");
await Bun.sleep(200);
console.log("line 3");
await Bun.sleep(200);
console.log("line 4");
await Bun.sleep(200);
console.log("line 5");