authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-11-26 00:36:33-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2024-11-26 00:36:33-05:00
logb0dcce93f7fca9ee4f8e4f2c0a34523b91b50c46
treec7a3ce094135d68f79c01761a9df9bd3c65fc5d0
parenta6af55cc6e81dd09e03d4b87e8079ce1fe57a36c
parentf6392b9526a457afe59f50abe97de397331037e3
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #22075 from ziglang/fix-broken-pipe

std.io.Poller: handle EPIPE as EOF

5 files changed, 17 insertions(+), 22 deletions(-)

.github/workflows/ci.yaml+1-1
...@@ -46,7 +46,7 @@ jobs:...@@ -46,7 +46,7 @@ jobs:
46 - name: Build and Test46 - name: Build and Test
47 run: sh ci/aarch64-linux-release.sh47 run: sh ci/aarch64-linux-release.sh
48 x86_64-macos-release:48 x86_64-macos-release:
49 runs-on: "macos-12"49 runs-on: "macos-13"
50 env:50 env:
51 ARCH: "x86_64"51 ARCH: "x86_64"
52 steps:52 steps:
CMakeLists.txt+1-6
...@@ -89,12 +89,7 @@ set(ZIG_SHARED_LLVM off CACHE BOOL "Prefer linking against shared LLVM libraries...@@ -89,12 +89,7 @@ set(ZIG_SHARED_LLVM off CACHE BOOL "Prefer linking against shared LLVM libraries
89set(ZIG_STATIC_LLVM ${ZIG_STATIC} CACHE BOOL "Prefer linking against static LLVM libraries")89set(ZIG_STATIC_LLVM ${ZIG_STATIC} CACHE BOOL "Prefer linking against static LLVM libraries")
90set(ZIG_STATIC_ZLIB ${ZIG_STATIC} CACHE BOOL "Prefer linking against static zlib")90set(ZIG_STATIC_ZLIB ${ZIG_STATIC} CACHE BOOL "Prefer linking against static zlib")
91set(ZIG_STATIC_ZSTD ${ZIG_STATIC} CACHE BOOL "Prefer linking against static zstd")91set(ZIG_STATIC_ZSTD ${ZIG_STATIC} CACHE BOOL "Prefer linking against static zstd")
92if(APPLE AND ZIG_STATIC)92set(ZIG_STATIC_CURSES OFF CACHE BOOL "Enable static linking against curses")
93 set(ZIG_STATIC_CURSES on)
94else()
95 set(ZIG_STATIC_CURSES off)
96endif()
97set(ZIG_STATIC_CURSES ${ZIG_STATIC_CURSES} CACHE BOOL "Prefer linking against static curses")
9893
99if (ZIG_SHARED_LLVM AND ZIG_STATIC_LLVM)94if (ZIG_SHARED_LLVM AND ZIG_STATIC_LLVM)
100 message(SEND_ERROR "-DZIG_SHARED_LLVM and -DZIG_STATIC_LLVM cannot both be enabled simultaneously")95 message(SEND_ERROR "-DZIG_SHARED_LLVM and -DZIG_STATIC_LLVM cannot both be enabled simultaneously")
lib/std/Target.zig+1-1
...@@ -531,7 +531,7 @@ pub const Os = struct {...@@ -531,7 +531,7 @@ pub const Os = struct {
531 },531 },
532 .macos => .{532 .macos => .{
533 .semver = .{533 .semver = .{
534 .min = .{ .major = 11, .minor = 7, .patch = 1 },534 .min = .{ .major = 13, .minor = 0, .patch = 0 },
535 .max = .{ .major = 15, .minor = 2, .patch = 0 },535 .max = .{ .major = 15, .minor = 2, .patch = 0 },
536 },536 },
537 },537 },
lib/std/io.zig+4-1
...@@ -646,7 +646,10 @@ pub fn Poller(comptime StreamEnum: type) type {...@@ -646,7 +646,10 @@ pub fn Poller(comptime StreamEnum: type) type {
646 // always check if there's some data waiting to be read first.646 // always check if there's some data waiting to be read first.
647 if (poll_fd.revents & posix.POLL.IN != 0) {647 if (poll_fd.revents & posix.POLL.IN != 0) {
648 const buf = try q.writableWithSize(bump_amt);648 const buf = try q.writableWithSize(bump_amt);
649 const amt = try posix.read(poll_fd.fd, buf);649 const amt = posix.read(poll_fd.fd, buf) catch |err| switch (err) {
650 error.BrokenPipe => 0, // Handle the same as EOF.
651 else => |e| return e,
652 };
650 q.update(amt);653 q.update(amt);
651 if (amt == 0) {654 if (amt == 0) {
652 // Remove the fd when the EOF condition is met.655 // Remove the fd when the EOF condition is met.
lib/std/process/Child.zig+10-13
...@@ -293,19 +293,16 @@ pub fn killPosix(self: *ChildProcess) !Term {...@@ -293,19 +293,16 @@ pub fn killPosix(self: *ChildProcess) !Term {
293 error.ProcessNotFound => return error.AlreadyTerminated,293 error.ProcessNotFound => return error.AlreadyTerminated,
294 else => return err,294 else => return err,
295 };295 };
296 try self.waitUnwrapped();296 self.waitUnwrapped();
297 return self.term.?;297 return self.term.?;
298}298}
299299
300/// Blocks until child process terminates and then cleans up all resources.300pub const WaitError = SpawnError || std.os.windows.GetProcessMemoryInfoError;
301pub fn wait(self: *ChildProcess) !Term {
302 const term = if (native_os == .windows)
303 try self.waitWindows()
304 else
305 try self.waitPosix();
306301
302/// Blocks until child process terminates and then cleans up all resources.
303pub fn wait(self: *ChildProcess) WaitError!Term {
304 const term = if (native_os == .windows) try self.waitWindows() else self.waitPosix();
307 self.id = undefined;305 self.id = undefined;
308
309 return term;306 return term;
310}307}
311308
...@@ -408,7 +405,7 @@ pub fn run(args: struct {...@@ -408,7 +405,7 @@ pub fn run(args: struct {
408 };405 };
409}406}
410407
411fn waitWindows(self: *ChildProcess) !Term {408fn waitWindows(self: *ChildProcess) WaitError!Term {
412 if (self.term) |term| {409 if (self.term) |term| {
413 self.cleanupStreams();410 self.cleanupStreams();
414 return term;411 return term;
...@@ -418,17 +415,17 @@ fn waitWindows(self: *ChildProcess) !Term {...@@ -418,17 +415,17 @@ fn waitWindows(self: *ChildProcess) !Term {
418 return self.term.?;415 return self.term.?;
419}416}
420417
421fn waitPosix(self: *ChildProcess) !Term {418fn waitPosix(self: *ChildProcess) SpawnError!Term {
422 if (self.term) |term| {419 if (self.term) |term| {
423 self.cleanupStreams();420 self.cleanupStreams();
424 return term;421 return term;
425 }422 }
426423
427 try self.waitUnwrapped();424 self.waitUnwrapped();
428 return self.term.?;425 return self.term.?;
429}426}
430427
431fn waitUnwrappedWindows(self: *ChildProcess) !void {428fn waitUnwrappedWindows(self: *ChildProcess) WaitError!void {
432 const result = windows.WaitForSingleObjectEx(self.id, windows.INFINITE, false);429 const result = windows.WaitForSingleObjectEx(self.id, windows.INFINITE, false);
433430
434 self.term = @as(SpawnError!Term, x: {431 self.term = @as(SpawnError!Term, x: {
...@@ -450,7 +447,7 @@ fn waitUnwrappedWindows(self: *ChildProcess) !void {...@@ -450,7 +447,7 @@ fn waitUnwrappedWindows(self: *ChildProcess) !void {
450 return result;447 return result;
451}448}
452449
453fn waitUnwrapped(self: *ChildProcess) !void {450fn waitUnwrapped(self: *ChildProcess) void {
454 const res: posix.WaitPidResult = res: {451 const res: posix.WaitPidResult = res: {
455 if (self.request_resource_usage_statistics) {452 if (self.request_resource_usage_statistics) {
456 switch (native_os) {453 switch (native_os) {