authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-01-08 15:07:03-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-01-09 20:47:24-08:00
logd66d0743d90f45f053bc41399bbc4b0adb0ffcef
tree98731157b4c730f022972b292ee130dc3d1bb9ef
parentd776ebc913aa2b4fb7f4ff6783cd5b67d009f1c5

std.Io.Threaded.operate: handle poll buffer exceeded


1 files changed, 72 insertions(+), 69 deletions(-)

lib/std/Io/Threaded.zig+72-69
......@@ -2277,81 +2277,84 @@ fn operate(userdata: ?*anyopaque, operations: []Io.Operation) void {
22772277
22782278 var poll_buffer: [poll_buffer_len]posix.pollfd = undefined;
22792279 var map_buffer: [poll_buffer_len]u8 = undefined; // poll_buffer index to operations index
2280 var poll_i: usize = 0;
2281
2282 // Put all the file reads with nonblocking enabled into the poll set.
2283 if (operations.len > poll_buffer.len) @panic("TODO");
2284
2285 for (operations, 0..) |*operation, operation_index| switch (operation.*) {
2286 .noop => continue,
2287 .file_read_streaming => |*o| {
2288 if (o.nonblocking) {
2289 o.result = error.WouldBlock;
2290 poll_buffer[poll_i] = .{
2291 .fd = o.file.handle,
2292 .events = posix.POLL.IN,
2293 .revents = undefined,
2294 };
2295 map_buffer[poll_i] = @intCast(operation_index);
2296 poll_i += 1;
2297 } else {
2298 o.result = fileReadStreaming(o.file, o.data) catch |err| switch (err) {
2299 error.Canceled => {
2300 setOperationsCanceled(operations[operation_index..]);
2301 return;
2302 },
2303 else => err,
2304 };
2280 var operation_index: usize = 0;
2281
2282 while (operation_index < operations.len) {
2283 var poll_i: usize = 0;
2284 while (operation_index < operations.len) : (operation_index += 1) {
2285 switch (operations[operation_index]) {
2286 .noop => continue,
2287 .file_read_streaming => |*o| {
2288 if (o.nonblocking) {
2289 o.result = error.WouldBlock;
2290 poll_buffer[poll_i] = .{
2291 .fd = o.file.handle,
2292 .events = posix.POLL.IN,
2293 .revents = 0,
2294 };
2295 if (map_buffer.len - poll_i == 0) break;
2296 map_buffer[poll_i] = @intCast(operation_index);
2297 poll_i += 1;
2298 } else {
2299 o.result = fileReadStreaming(o.file, o.data) catch |err| switch (err) {
2300 error.Canceled => {
2301 setOperationsError(operations[operation_index..], error.Canceled);
2302 return;
2303 },
2304 else => err,
2305 };
2306 }
2307 },
23052308 }
2306 },
2307 };
2308
2309 if (poll_i == 0) {
2310 @branchHint(.likely);
2311 return;
2312 }
2309 }
23132310
2314 while (true) {
2315 const syscall = Syscall.start() catch |err| switch (err) {
2316 error.Canceled => {
2317 setAllOperationsError(operations, map_buffer[0..poll_i], error.Canceled);
2318 return;
2319 },
2320 };
2321 const poll_rc = posix.system.poll(&poll_buffer, poll_i, -1);
2322 syscall.finish();
2323 switch (posix.errno(poll_rc)) {
2324 .SUCCESS => {
2325 if (poll_rc == 0) {
2326 // Spurious timeout; handle same as INTR.
2327 continue;
2328 }
2329 break;
2330 },
2331 .INTR => continue,
2332 .NOMEM => {
2333 setAllOperationsError(operations, map_buffer[0..poll_i], error.SystemResources);
2334 return;
2335 },
2336 else => {
2337 setAllOperationsError(operations, map_buffer[0..poll_i], error.Unexpected);
2338 return;
2339 },
2311 if (poll_i == 0) {
2312 @branchHint(.likely);
2313 return;
23402314 }
2341 }
23422315
2343 for (poll_buffer[0..poll_i], map_buffer[0..poll_i]) |*poll_fd, operation_index| {
2344 if (poll_fd.revents == 0) continue;
2345 switch (operations[operation_index]) {
2346 .noop => unreachable,
2347 .file_read_streaming => |*o| {
2348 o.result = fileReadStreaming(o.file, o.data);
2349 },
2316 while (true) {
2317 const syscall = Syscall.start() catch |err| switch (err) {
2318 error.Canceled => {
2319 setPollOperationsError(operations, map_buffer[0..poll_i], error.Canceled);
2320 setOperationsError(operations[operation_index..], error.Canceled);
2321 return;
2322 },
2323 };
2324 const poll_rc = posix.system.poll(&poll_buffer, poll_i, -1);
2325 syscall.finish();
2326 switch (posix.errno(poll_rc)) {
2327 .SUCCESS => {
2328 if (poll_rc == 0) {
2329 // Spurious timeout; handle same as INTR.
2330 continue;
2331 }
2332 for (poll_buffer[0..poll_i], map_buffer[0..poll_i]) |*poll_fd, i| {
2333 if (poll_fd.revents == 0) continue;
2334 switch (operations[i]) {
2335 .noop => unreachable,
2336 .file_read_streaming => |*o| {
2337 o.result = fileReadStreaming(o.file, o.data);
2338 },
2339 }
2340 }
2341 break;
2342 },
2343 .INTR => continue,
2344 .NOMEM => {
2345 setPollOperationsError(operations, map_buffer[0..poll_i], error.SystemResources);
2346 break;
2347 },
2348 else => {
2349 setPollOperationsError(operations, map_buffer[0..poll_i], error.Unexpected);
2350 break;
2351 },
2352 }
23502353 }
23512354 }
23522355}
23532356
2354fn setAllOperationsError(
2357fn setPollOperationsError(
23552358 operations: []Io.Operation,
23562359 map: []const u8,
23572360 err: error{ Canceled, SystemResources, Unexpected },
......@@ -2362,10 +2365,10 @@ fn setAllOperationsError(
23622365 };
23632366}
23642367
2365fn setOperationsCanceled(operations: []Io.Operation) void {
2368fn setOperationsError(operations: []Io.Operation, err: error{ Canceled, SystemResources, Unexpected }) void {
23662369 for (operations) |*op| switch (op.*) {
23672370 .noop => unreachable,
2368 inline else => |*o| o.result = error.Canceled,
2371 inline else => |*o| o.result = err,
23692372 };
23702373}
23712374