| author | |
| committer | |
| log | 0deaf9957c34eceecd3cb7b0033e447ef94addc5 |
| tree | 19c4abf6fda15cd19107a91db05d6390fd8d0e41 |
| parent | d63172a35da5d493aef72aa074afa90ac5bb619a |
- no timeout
- no n_wait
- infallible5 files changed, 34 insertions(+), 54 deletions(-)
lib/std/Io.zig+4-15| ... | ... | @@ -148,7 +148,7 @@ pub const VTable = struct { |
| 148 | 148 | futexWaitUncancelable: *const fn (?*anyopaque, ptr: *const u32, expected: u32) void, |
| 149 | 149 | futexWake: *const fn (?*anyopaque, ptr: *const u32, max_waiters: u32) void, |
| 150 | 150 | |
| 151 | operate: *const fn (?*anyopaque, []Operation, n_wait: usize, Timeout) OperateError!void, | |
| 151 | operate: *const fn (?*anyopaque, []Operation) void, | |
| 152 | 152 | |
| 153 | 153 | dirCreateDir: *const fn (?*anyopaque, Dir, []const u8, Dir.Permissions) Dir.CreateDirError!void, |
| 154 | 154 | dirCreateDirPath: *const fn (?*anyopaque, Dir, []const u8, Dir.Permissions) Dir.CreateDirPathError!Dir.CreatePathStatus, |
| ... | ... | @@ -257,22 +257,11 @@ pub const Operation = union(enum) { |
| 257 | 257 | }; |
| 258 | 258 | }; |
| 259 | 259 | |
| 260 | pub const OperateError = error{ Canceled, Timeout }; | |
| 261 | ||
| 262 | 260 | /// Performs all `operations` in a non-deterministic order. Returns after all |
| 263 | /// `operations` have been attempted. The degree to which the operations are | |
| 261 | /// `operations` have been completed. The degree to which the operations are | |
| 264 | 262 | /// performed concurrently is determined by the `Io` implementation. |
| 265 | /// | |
| 266 | /// `n_wait` is an amount of operations between `0` and `operations.len` that | |
| 267 | /// determines how many attempted operations must complete before `operate` | |
| 268 | /// returns. Operation completion is defined by returning a value other than | |
| 269 | /// `error.WouldBlock`. If the operation cannot return `error.WouldBlock`, it | |
| 270 | /// always counts as completing. | |
| 271 | /// | |
| 272 | /// In the event `error.Canceled` is returned, any number of `operations` may | |
| 273 | /// still have been completed successfully. | |
| 274 | pub fn operate(io: Io, operations: []Operation, n_wait: usize, timeout: Timeout) OperateError!void { | |
| 275 | return io.vtable.operate(io.userdata, operations, n_wait, timeout); | |
| 263 | pub fn operate(io: Io, operations: []Operation) void { | |
| 264 | return io.vtable.operate(io.userdata, operations); | |
| 276 | 265 | } |
| 277 | 266 | |
| 278 | 267 | pub const Limit = enum(usize) { |
lib/std/Io/File.zig+1-1| ... | ... | @@ -531,7 +531,7 @@ pub fn readStreaming(file: File, io: Io, buffer: []const []u8) Reader.Error!usiz |
| 531 | 531 | .data = buffer, |
| 532 | 532 | .result = undefined, |
| 533 | 533 | } }; |
| 534 | io.vtable.operate(io.userdata, (&operation)[0..1], 1, .none) catch unreachable; | |
| 534 | io.vtable.operate(io.userdata, (&operation)[0..1]); | |
| 535 | 535 | return operation.file_read_streaming.result; |
| 536 | 536 | } |
| 537 | 537 |
lib/std/Io/Threaded.zig+28-33| ... | ... | @@ -2268,20 +2268,15 @@ fn futexWake(userdata: ?*anyopaque, ptr: *const u32, max_waiters: u32) void { |
| 2268 | 2268 | Thread.futexWake(ptr, max_waiters); |
| 2269 | 2269 | } |
| 2270 | 2270 | |
| 2271 | fn operate(userdata: ?*anyopaque, operations: []Io.Operation, n_wait: usize, timeout: Io.Timeout) Io.OperateError!void { | |
| 2271 | fn operate(userdata: ?*anyopaque, operations: []Io.Operation) void { | |
| 2272 | 2272 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 2273 | const t_io = ioBasic(t); | |
| 2273 | _ = t; | |
| 2274 | 2274 | |
| 2275 | 2275 | if (is_windows) @panic("TODO"); |
| 2276 | 2276 | |
| 2277 | const deadline = timeout.toDeadline(t_io) catch |err| switch (err) { | |
| 2278 | error.UnsupportedClock, error.Unexpected => null, | |
| 2279 | }; | |
| 2280 | ||
| 2281 | 2277 | var poll_buffer: [100]posix.pollfd = undefined; |
| 2282 | 2278 | var map_buffer: [poll_buffer.len]u8 = undefined; // poll_buffer index to operations index |
| 2283 | 2279 | var poll_i: usize = 0; |
| 2284 | var completed: usize = 0; | |
| 2285 | 2280 | |
| 2286 | 2281 | // Put all the file reads with nonblocking enabled into the poll set. |
| 2287 | 2282 | if (operations.len > poll_buffer.len) @panic("TODO"); |
| ... | ... | @@ -2302,7 +2297,6 @@ fn operate(userdata: ?*anyopaque, operations: []Io.Operation, n_wait: usize, tim |
| 2302 | 2297 | poll_i += 1; |
| 2303 | 2298 | } else { |
| 2304 | 2299 | o.result = fileReadStreaming(o.file, o.data); |
| 2305 | completed += 1; | |
| 2306 | 2300 | } |
| 2307 | 2301 | }, |
| 2308 | 2302 | }; |
| ... | ... | @@ -2312,41 +2306,42 @@ fn operate(userdata: ?*anyopaque, operations: []Io.Operation, n_wait: usize, tim |
| 2312 | 2306 | return; |
| 2313 | 2307 | } |
| 2314 | 2308 | |
| 2315 | const max_poll_ms = std.math.maxInt(i32); | |
| 2316 | ||
| 2317 | while (completed < n_wait) { | |
| 2318 | const timeout_ms: i32 = if (deadline) |d| t: { | |
| 2319 | const duration = d.durationFromNow(t_io) catch @panic("TODO make this unreachable"); | |
| 2320 | if (duration.raw.nanoseconds <= 0) return error.Timeout; | |
| 2321 | break :t @intCast(@min(max_poll_ms, duration.raw.toMilliseconds())); | |
| 2322 | } else -1; | |
| 2323 | const syscall = try Syscall.start(); | |
| 2324 | const poll_rc = posix.system.poll(&poll_buffer, poll_i, timeout_ms); | |
| 2309 | while (true) { | |
| 2310 | const syscall = Syscall.start() catch |err| switch (err) { | |
| 2311 | error.Canceled => { | |
| 2312 | for (map_buffer[0..poll_i]) |operation_index| { | |
| 2313 | switch (operations[operation_index]) { | |
| 2314 | .noop => unreachable, | |
| 2315 | inline else => |*o| o.result = error.Canceled, | |
| 2316 | } | |
| 2317 | } | |
| 2318 | return; | |
| 2319 | }, | |
| 2320 | }; | |
| 2321 | const poll_rc = posix.system.poll(&poll_buffer, poll_i, -1); | |
| 2325 | 2322 | syscall.finish(); |
| 2326 | 2323 | switch (posix.errno(poll_rc)) { |
| 2327 | 2324 | .SUCCESS => { |
| 2328 | 2325 | if (poll_rc == 0) { |
| 2329 | // Although spurious timeouts are OK, when no deadline | |
| 2330 | // is passed we must not return `error.Timeout`. | |
| 2331 | if (deadline == null) continue; | |
| 2332 | return error.Timeout; | |
| 2333 | } | |
| 2334 | for (poll_buffer[0..poll_i], map_buffer[0..poll_i]) |*poll_fd, operation_index| { | |
| 2335 | if (poll_fd.revents == 0) continue; | |
| 2336 | poll_fd.fd = -1; // Disarm this operation. | |
| 2337 | switch (operations[operation_index]) { | |
| 2338 | .noop => unreachable, | |
| 2339 | .file_read_streaming => |*o| { | |
| 2340 | o.result = fileReadStreaming(o.file, o.data); | |
| 2341 | completed += 1; | |
| 2342 | }, | |
| 2343 | } | |
| 2326 | // Spurious timeout; handle same as INTR. | |
| 2327 | continue; | |
| 2344 | 2328 | } |
| 2329 | break; | |
| 2345 | 2330 | }, |
| 2346 | 2331 | .INTR => continue, |
| 2347 | 2332 | else => @panic("TODO handle unexpected error from poll()"), |
| 2348 | 2333 | } |
| 2349 | 2334 | } |
| 2335 | ||
| 2336 | for (poll_buffer[0..poll_i], map_buffer[0..poll_i]) |*poll_fd, operation_index| { | |
| 2337 | if (poll_fd.revents == 0) continue; | |
| 2338 | switch (operations[operation_index]) { | |
| 2339 | .noop => unreachable, | |
| 2340 | .file_read_streaming => |*o| { | |
| 2341 | o.result = fileReadStreaming(o.file, o.data); | |
| 2342 | }, | |
| 2343 | } | |
| 2344 | } | |
| 2350 | 2345 | } |
| 2351 | 2346 | |
| 2352 | 2347 | const dirCreateDir = switch (native_os) { |
lib/std/process.zig-2| ... | ... | @@ -502,7 +502,6 @@ pub const RunOptions = struct { |
| 502 | 502 | create_no_window: bool = true, |
| 503 | 503 | /// Darwin-only. Disable ASLR for the child process. |
| 504 | 504 | disable_aslr: bool = false, |
| 505 | timeout: Io.Timeout = .none, | |
| 506 | 505 | }; |
| 507 | 506 | |
| 508 | 507 | pub const RunResult = struct { |
| ... | ... | @@ -544,7 +543,6 @@ pub fn run(gpa: Allocator, io: Io, options: RunOptions) RunError!RunResult { |
| 544 | 543 | .stderr = &stderr, |
| 545 | 544 | .stdout_limit = options.stdout_limit, |
| 546 | 545 | .stderr_limit = options.stderr_limit, |
| 547 | .timeout = options.timeout, | |
| 548 | 546 | }); |
| 549 | 547 | |
| 550 | 548 | return .{ |
lib/std/process/Child.zig+1-3| ... | ... | @@ -138,7 +138,6 @@ pub const CollectOutputOptions = struct { |
| 138 | 138 | allocator: ?Allocator = null, |
| 139 | 139 | stdout_limit: Io.Limit = .unlimited, |
| 140 | 140 | stderr_limit: Io.Limit = .unlimited, |
| 141 | timeout: Io.Timeout = .none, | |
| 142 | 141 | }; |
| 143 | 142 | |
| 144 | 143 | /// Collect the output from the process's stdout and stderr. Will return once |
| ... | ... | @@ -174,7 +173,7 @@ pub fn collectOutput(child: *const Child, io: Io, options: CollectOutputOptions) |
| 174 | 173 | var all_done = true; |
| 175 | 174 | var any_canceled = false; |
| 176 | 175 | var other_err: (error{StreamTooLong} || Io.File.Reader.Error)!void = {}; |
| 177 | const op_result = io.vtable.operate(io.userdata, &reads, 1, options.timeout); | |
| 176 | io.vtable.operate(io.userdata, &reads); | |
| 178 | 177 | for (&reads, &lists, &limits, &dones) |*read, list, limit, *done| { |
| 179 | 178 | if (done.*) continue; |
| 180 | 179 | const n = read.file_read_streaming.result catch |err| switch (err) { |
| ... | ... | @@ -197,7 +196,6 @@ pub fn collectOutput(child: *const Child, io: Io, options: CollectOutputOptions) |
| 197 | 196 | if (list.items.len > @intFromEnum(limit)) other_err = error.StreamTooLong; |
| 198 | 197 | } |
| 199 | 198 | if (any_canceled) return error.Canceled; |
| 200 | try op_result; // could be error.Canceled | |
| 201 | 199 | try other_err; |
| 202 | 200 | if (all_done) return; |
| 203 | 201 | } |