| ... | @@ -1323,6 +1323,7 @@ fn waitForApcOrAlert() void { | ... | @@ -1323,6 +1323,7 @@ fn waitForApcOrAlert() void { |
| 1323 | | 1323 | |
| 1324 | const max_iovecs_len = 8; | 1324 | const max_iovecs_len = 8; |
| 1325 | const splat_buffer_size = 64; | 1325 | const splat_buffer_size = 64; |
| | 1326 | const poll_buffer_len = 100; |
| 1326 | const default_PATH = "/usr/local/bin:/bin/:/usr/bin"; | 1327 | const default_PATH = "/usr/local/bin:/bin/:/usr/bin"; |
| 1327 | | 1328 | |
| 1328 | comptime { | 1329 | comptime { |
| ... | @@ -2455,15 +2456,13 @@ fn operate(userdata: ?*anyopaque, operations: []Io.Operation) void { | ... | @@ -2455,15 +2456,13 @@ fn operate(userdata: ?*anyopaque, operations: []Io.Operation) void { |
| 2455 | | 2456 | |
| 2456 | if (is_windows) @panic("TODO"); | 2457 | if (is_windows) @panic("TODO"); |
| 2457 | | 2458 | |
| 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 index | 2460 | 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; |
| 2461 | | 2462 | |
| 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"); |
| 2464 | | 2465 | |
| 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 | } |
| 2516 | | 2523 | |
| ... | @@ -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 | } |
| 2527 | | 2534 | |
| | 2535 | fn 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 | |
| | 2546 | fn 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 | |
| 2528 | const dirCreateDir = switch (native_os) { | 2553 | const dirCreateDir = switch (native_os) { |
| 2529 | .windows => dirCreateDirWindows, | 2554 | .windows => dirCreateDirWindows, |
| 2530 | .wasi => dirCreateDirWasi, | 2555 | .wasi => dirCreateDirWasi, |