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 {...@@ -1323,6 +1323,7 @@ fn waitForApcOrAlert() void {
13231323
1324const max_iovecs_len = 8;1324const max_iovecs_len = 8;
1325const splat_buffer_size = 64;1325const splat_buffer_size = 64;
1326const poll_buffer_len = 100;
1326const default_PATH = "/usr/local/bin:/bin/:/usr/bin";1327const default_PATH = "/usr/local/bin:/bin/:/usr/bin";
13271328
1328comptime {1329comptime {
...@@ -2455,15 +2456,13 @@ fn operate(userdata: ?*anyopaque, operations: []Io.Operation) void {...@@ -2455,15 +2456,13 @@ fn operate(userdata: ?*anyopaque, operations: []Io.Operation) void {
24552456
2456 if (is_windows) @panic("TODO");2457 if (is_windows) @panic("TODO");
24572458
2458 var poll_buffer: [100]posix.pollfd = undefined;2459 var poll_buffer: [poll_buffer_len]posix.pollfd = undefined;
2459 var map_buffer: [poll_buffer.len]u8 = undefined; // poll_buffer index to operations index2460 var map_buffer: [poll_buffer_len]u8 = undefined; // poll_buffer index to operations index
2460 var poll_i: usize = 0;2461 var poll_i: usize = 0;
24612462
2462 // Put all the file reads with nonblocking enabled into the poll set.2463 // Put all the file reads with nonblocking enabled into the poll set.
2463 if (operations.len > poll_buffer.len) @panic("TODO");2464 if (operations.len > poll_buffer.len) @panic("TODO");
24642465
2465 // TODO if any operation is canceled, cancel the rest
2466
2467 for (operations, 0..) |*operation, operation_index| switch (operation.*) {2466 for (operations, 0..) |*operation, operation_index| switch (operation.*) {
2468 .noop => continue,2467 .noop => continue,
2469 .file_read_streaming => |*o| {2468 .file_read_streaming => |*o| {
...@@ -2477,7 +2476,13 @@ fn operate(userdata: ?*anyopaque, operations: []Io.Operation) void {...@@ -2477,7 +2476,13 @@ fn operate(userdata: ?*anyopaque, operations: []Io.Operation) void {
2477 map_buffer[poll_i] = @intCast(operation_index);2476 map_buffer[poll_i] = @intCast(operation_index);
2478 poll_i += 1;2477 poll_i += 1;
2479 } else {2478 } 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 };
2481 }2486 }
2482 },2487 },
2483 };2488 };
...@@ -2490,12 +2495,7 @@ fn operate(userdata: ?*anyopaque, operations: []Io.Operation) void {...@@ -2490,12 +2495,7 @@ fn operate(userdata: ?*anyopaque, operations: []Io.Operation) void {
2490 while (true) {2495 while (true) {
2491 const syscall = Syscall.start() catch |err| switch (err) {2496 const syscall = Syscall.start() catch |err| switch (err) {
2492 error.Canceled => {2497 error.Canceled => {
2493 for (map_buffer[0..poll_i]) |operation_index| {2498 setAllOperationsError(operations, map_buffer[0..poll_i], error.Canceled);
2494 switch (operations[operation_index]) {
2495 .noop => unreachable,
2496 inline else => |*o| o.result = error.Canceled,
2497 }
2498 }
2499 return;2499 return;
2500 },2500 },
2501 };2501 };
...@@ -2510,7 +2510,14 @@ fn operate(userdata: ?*anyopaque, operations: []Io.Operation) void {...@@ -2510,7 +2510,14 @@ fn operate(userdata: ?*anyopaque, operations: []Io.Operation) void {
2510 break;2510 break;
2511 },2511 },
2512 .INTR => continue,2512 .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 },
2514 }2521 }
2515 }2522 }
25162523
...@@ -2525,6 +2532,24 @@ fn operate(userdata: ?*anyopaque, operations: []Io.Operation) void {...@@ -2525,6 +2532,24 @@ fn operate(userdata: ?*anyopaque, operations: []Io.Operation) void {
2525 }2532 }
2526}2533}
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
2528const dirCreateDir = switch (native_os) {2553const dirCreateDir = switch (native_os) {
2529 .windows => dirCreateDirWindows,2554 .windows => dirCreateDirWindows,
2530 .wasi => dirCreateDirWasi,2555 .wasi => dirCreateDirWasi,