authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-01-08 14:10:31-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-01-30 12:10:01-08:00
logae2d71b65ed995978e9d2492fde3645313d790cb
tree3c5405b0587e219332df4c2a15dc2a4c8f33c528
parentf391adc3af832cf9a5ec7be8f7c23134fc07984a

std.Io.Threaded.operate: handle cancelation and poll errors


1 files changed, 37 insertions(+), 12 deletions(-)

lib/std/Io/Threaded.zig+37-12
......@@ -1323,6 +1323,7 @@ fn waitForApcOrAlert() void {
13231323
13241324const max_iovecs_len = 8;
13251325const splat_buffer_size = 64;
1326const poll_buffer_len = 100;
13261327const default_PATH = "/usr/local/bin:/bin/:/usr/bin";
13271328
13281329comptime {
......@@ -2455,15 +2456,13 @@ fn operate(userdata: ?*anyopaque, operations: []Io.Operation) void {
24552456
24562457 if (is_windows) @panic("TODO");
24572458
2458 var poll_buffer: [100]posix.pollfd = undefined;
2459 var map_buffer: [poll_buffer.len]u8 = undefined; // poll_buffer index to operations index
2459 var poll_buffer: [poll_buffer_len]posix.pollfd = undefined;
2460 var map_buffer: [poll_buffer_len]u8 = undefined; // poll_buffer index to operations index
24602461 var poll_i: usize = 0;
24612462
24622463 // Put all the file reads with nonblocking enabled into the poll set.
24632464 if (operations.len > poll_buffer.len) @panic("TODO");
24642465
2465 // TODO if any operation is canceled, cancel the rest
2466
24672466 for (operations, 0..) |*operation, operation_index| switch (operation.*) {
24682467 .noop => continue,
24692468 .file_read_streaming => |*o| {
......@@ -2477,7 +2476,13 @@ fn operate(userdata: ?*anyopaque, operations: []Io.Operation) void {
24772476 map_buffer[poll_i] = @intCast(operation_index);
24782477 poll_i += 1;
24792478 } else {
2480 o.result = fileReadStreaming(o.file, o.data);
2479 o.result = fileReadStreaming(o.file, o.data) catch |err| switch (err) {
2480 error.Canceled => {
2481 setOperationsCanceled(operations[operation_index..]);
2482 return;
2483 },
2484 else => err,
2485 };
24812486 }
24822487 },
24832488 };
......@@ -2490,12 +2495,7 @@ fn operate(userdata: ?*anyopaque, operations: []Io.Operation) void {
24902495 while (true) {
24912496 const syscall = Syscall.start() catch |err| switch (err) {
24922497 error.Canceled => {
2493 for (map_buffer[0..poll_i]) |operation_index| {
2494 switch (operations[operation_index]) {
2495 .noop => unreachable,
2496 inline else => |*o| o.result = error.Canceled,
2497 }
2498 }
2498 setAllOperationsError(operations, map_buffer[0..poll_i], error.Canceled);
24992499 return;
25002500 },
25012501 };
......@@ -2510,7 +2510,14 @@ fn operate(userdata: ?*anyopaque, operations: []Io.Operation) void {
25102510 break;
25112511 },
25122512 .INTR => continue,
2513 else => @panic("TODO handle unexpected error from poll()"),
2513 .NOMEM => {
2514 setAllOperationsError(operations, map_buffer[0..poll_i], error.SystemResources);
2515 return;
2516 },
2517 else => {
2518 setAllOperationsError(operations, map_buffer[0..poll_i], error.Unexpected);
2519 return;
2520 },
25142521 }
25152522 }
25162523
......@@ -2525,6 +2532,24 @@ fn operate(userdata: ?*anyopaque, operations: []Io.Operation) void {
25252532 }
25262533}
25272534
2535fn setAllOperationsError(
2536 operations: []Io.Operation,
2537 map: []const u8,
2538 err: error{ Canceled, SystemResources, Unexpected },
2539) void {
2540 for (map) |operation_index| switch (operations[operation_index]) {
2541 .noop => unreachable,
2542 inline else => |*o| o.result = err,
2543 };
2544}
2545
2546fn setOperationsCanceled(operations: []Io.Operation) void {
2547 for (operations) |*op| switch (op.*) {
2548 .noop => unreachable,
2549 inline else => |*o| o.result = error.Canceled,
2550 };
2551}
2552
25282553const dirCreateDir = switch (native_os) {
25292554 .windows => dirCreateDirWindows,
25302555 .wasi => dirCreateDirWasi,