From f79f0d01b9fa06e1982b9c8691f060ade7437ea8 Mon Sep 17 00:00:00 2001 From: Zack Radisic <56137411+zackradisic@users.noreply.github.com> Date: Mon, 4 Mar 2024 17:47:11 -0800 Subject: [PATCH] move `close_handle` to flags in `PipeWriter` and fix shell hanging --- src/io/PipeReader.zig | 11 ++++++----- src/shell/interpreter.zig | 15 ++++++++------- src/shell/subproc.zig | 3 ++- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/src/io/PipeReader.zig b/src/io/PipeReader.zig index f724edf9ea..8b721969b2 100644 --- a/src/io/PipeReader.zig +++ b/src/io/PipeReader.zig @@ -624,7 +624,6 @@ const PosixBufferedReader = struct { _buffer: std.ArrayList(u8) = std.ArrayList(u8).init(bun.default_allocator), vtable: BufferedReaderVTable, flags: Flags = .{}, - close_handle: bool = true, const Flags = packed struct { is_done: bool = false, @@ -632,6 +631,7 @@ const PosixBufferedReader = struct { nonblocking: bool = false, received_eof: bool = false, closed_without_reporting: bool = false, + close_handle: bool = true, }; pub fn init(comptime Type: type) PosixBufferedReader { @@ -704,7 +704,7 @@ const PosixBufferedReader = struct { if (this.getFd() != bun.invalid_fd) { std.debug.assert(!this.flags.closed_without_reporting); this.flags.closed_without_reporting = true; - if (this.close_handle) this.handle.close(this, {}); + if (this.flags.close_handle) this.handle.close(this, {}); } } @@ -748,7 +748,7 @@ const PosixBufferedReader = struct { fn finish(this: *PosixBufferedReader) void { if (this.handle != .closed or this.flags.closed_without_reporting) { - if (this.close_handle) this.closeHandle(); + if (this.flags.close_handle) this.closeHandle(); return; } @@ -763,11 +763,11 @@ const PosixBufferedReader = struct { return; } - if (this.close_handle) this.handle.close(this, done); + if (this.flags.close_handle) this.handle.close(this, done); } pub fn done(this: *PosixBufferedReader) void { - if (this.handle != .closed and this.close_handle) { + if (this.handle != .closed and this.flags.close_handle) { this.closeHandle(); return; } else if (this.flags.closed_without_reporting) { @@ -890,6 +890,7 @@ pub const WindowsBufferedReader = struct { nonblocking: bool = false, received_eof: bool = false, closed_without_reporting: bool = false, + close_handle: bool = true, }; pub fn init(comptime Type: type) WindowsOutputReader { diff --git a/src/shell/interpreter.zig b/src/shell/interpreter.zig index b7fa0659b1..f47c596ab7 100644 --- a/src/shell/interpreter.zig +++ b/src/shell/interpreter.zig @@ -856,6 +856,7 @@ pub const Interpreter = struct { .pipe => { const bufio: *bun.ByteList = this.buffered_stderr(); bufio.appendFmt(bun.default_allocator, fmt, args) catch bun.outOfMemory(); + ctx.parent.childDone(ctx, 1); }, .ignore => {}, } @@ -3896,12 +3897,12 @@ pub const Interpreter = struct { } pub fn fromStr(str: []const u8) ?Builtin.Kind { - // if (!bun.Environment.isWindows) { - // if (bun.strings.eqlComptime(str, "cat")) { - // log("Cat builtin disabled on posix for now", .{}); - // return null; - // } - // } + if (!bun.Environment.isWindows) { + if (bun.strings.eqlComptime(str, "cat")) { + log("Cat builtin disabled on posix for now", .{}); + return null; + } + } @setEvalBranchQuota(5000); const tyinfo = @typeInfo(Builtin.Kind); inline for (tyinfo.Enum.fields) |field| { @@ -8577,7 +8578,7 @@ pub const Interpreter = struct { log("IOReader(0x{x}, fd={}) create", .{ @intFromPtr(this), fd }); if (bun.Environment.isPosix) { - this.reader.close_handle = false; + this.reader.flags.close_handle = false; } if (bun.Environment.isWindows) { diff --git a/src/shell/subproc.zig b/src/shell/subproc.zig index cde7f7e487..1b500615f1 100644 --- a/src/shell/subproc.zig +++ b/src/shell/subproc.zig @@ -780,6 +780,7 @@ pub const PipeReader = struct { pub fn isDone(this: *CapturedWriter, just_written: usize) bool { if (this.dead) return true; + if (this.writer.is_done) return true; const p = this.parent(); if (p.state == .pending) return false; return this.written + just_written >= p.buffered_output.slice().len; @@ -958,7 +959,7 @@ pub const PipeReader = struct { } pub fn onReaderDone(this: *PipeReader) void { - log("onReaderDone({x})", .{@intFromPtr(this)}); + log("onReaderDone(0x{x}, {s})", .{ @intFromPtr(this), @tagName(this.out_type) }); const owned = this.toOwnedSlice(); this.state = .{ .done = owned }; if (!this.isDone()) return;