| ... | @@ -2636,8 +2636,9 @@ fn operate(userdata: ?*anyopaque, operation: Io.Operation) Io.Cancelable!Io.Oper | ... | @@ -2636,8 +2636,9 @@ fn operate(userdata: ?*anyopaque, operation: Io.Operation) Io.Cancelable!Io.Oper |
| 2636 | .net_receive => |*o| return .{ .net_receive = o: { | 2636 | .net_receive => |*o| return .{ .net_receive = o: { |
| 2637 | if (!have_networking) break :o .{ error.NetworkDown, 0 }; | 2637 | if (!have_networking) break :o .{ error.NetworkDown, 0 }; |
| 2638 | if (is_windows) break :o netReceiveWindows(t, o.socket_handle, o.message_buffer, o.data_buffer, o.flags); | 2638 | if (is_windows) break :o netReceiveWindows(t, o.socket_handle, o.message_buffer, o.data_buffer, o.flags); |
| 2639 | netReceivePosix(o.socket_handle, &o.message_buffer[0], o.data_buffer, o.flags) catch |err| switch (err) { | 2639 | netReceivePosix(o.socket_handle, &o.message_buffer[0], o.data_buffer, o.flags, false) catch |err| switch (err) { |
| 2640 | error.Canceled => |e| return e, | 2640 | error.Canceled => |e| return e, |
| | 2641 | error.WouldBlock => unreachable, |
| 2641 | else => |e| break :o .{ e, 0 }, | 2642 | else => |e| break :o .{ e, 0 }, |
| 2642 | }; | 2643 | }; |
| 2643 | break :o .{ null, 1 }; | 2644 | break :o .{ null, 1 }; |
| ... | @@ -2846,19 +2847,41 @@ fn batchAwaitConcurrent(userdata: ?*anyopaque, b: *Io.Batch, timeout: Io.Timeout | ... | @@ -2846,19 +2847,41 @@ fn batchAwaitConcurrent(userdata: ?*anyopaque, b: *Io.Batch, timeout: Io.Timeout |
| 2846 | { | 2847 | { |
| 2847 | var index = b.submitted.head; | 2848 | var index = b.submitted.head; |
| 2848 | while (index != .none) { | 2849 | while (index != .none) { |
| 2849 | const submission = &b.storage[index.toIndex()].submission; | 2850 | const storage = &b.storage[index.toIndex()]; |
| | 2851 | const submission = storage.submission; |
| 2850 | switch (submission.operation) { | 2852 | switch (submission.operation) { |
| 2851 | .file_read_streaming => |o| try poll_storage.add(o.file.handle, posix.POLL.IN | posix.POLL.ERR), | 2853 | .file_read_streaming => |o| try poll_storage.add(o.file.handle, posix.POLL.IN | posix.POLL.ERR), |
| 2852 | .file_write_streaming => |o| try poll_storage.add(o.file.handle, posix.POLL.OUT | posix.POLL.ERR), | 2854 | .file_write_streaming => |o| try poll_storage.add(o.file.handle, posix.POLL.OUT | posix.POLL.ERR), |
| 2853 | .device_io_control => |o| try poll_storage.add(o.file.handle, posix.POLL.IN | posix.POLL.OUT | posix.POLL.ERR), | 2855 | .device_io_control => |o| try poll_storage.add(o.file.handle, posix.POLL.IN | posix.POLL.OUT | posix.POLL.ERR), |
| 2854 | .net_receive => |o| try poll_storage.add(o.socket_handle, posix.POLL.IN | posix.POLL.ERR), | 2856 | .net_receive => |*o| nb: { |
| | 2857 | var data_i: usize = 0; |
| | 2858 | const result: Io.Operation.Result = .{ .net_receive = for (o.message_buffer, 0..) |*msg, msg_i| { |
| | 2859 | const remaining_data_buffer = o.data_buffer[data_i..]; |
| | 2860 | netReceivePosix(o.socket_handle, msg, remaining_data_buffer, o.flags, true) catch |err| switch (err) { |
| | 2861 | error.Canceled => |e| return e, |
| | 2862 | error.WouldBlock => { |
| | 2863 | if (msg_i != 0) break .{ null, msg_i }; |
| | 2864 | try poll_storage.add(o.socket_handle, posix.POLL.IN | posix.POLL.ERR); |
| | 2865 | break :nb; |
| | 2866 | }, |
| | 2867 | else => |e| break .{ e, 0 }, |
| | 2868 | }; |
| | 2869 | data_i += msg.data.len; |
| | 2870 | } else .{ null, o.message_buffer.len } }; |
| | 2871 | switch (b.completed.tail) { |
| | 2872 | .none => b.completed.head = index, |
| | 2873 | else => |tail_index| b.storage[tail_index.toIndex()].completion.node.next = index, |
| | 2874 | } |
| | 2875 | storage.* = .{ .completion = .{ .node = .{ .next = .none }, .result = result } }; |
| | 2876 | b.completed.tail = index; |
| | 2877 | }, |
| 2855 | } | 2878 | } |
| 2856 | index = submission.node.next; | 2879 | index = submission.node.next; |
| 2857 | } | 2880 | } |
| 2858 | } | 2881 | } |
| 2859 | switch (poll_storage.len) { | 2882 | switch (poll_storage.len) { |
| 2860 | 0 => return, | 2883 | 0 => return, |
| 2861 | 1 => if (timeout == .none) { | 2884 | 1 => if (timeout == .none and b.completed.head == .none) { |
| 2862 | const index = b.submitted.head; | 2885 | const index = b.submitted.head; |
| 2863 | const storage = &b.storage[index.toIndex()]; | 2886 | const storage = &b.storage[index.toIndex()]; |
| 2864 | const result = try operate(t, storage.submission.operation); | 2887 | const result = try operate(t, storage.submission.operation); |
| ... | @@ -13221,7 +13244,8 @@ fn netReceivePosix( | ... | @@ -13221,7 +13244,8 @@ fn netReceivePosix( |
| 13221 | message: *net.IncomingMessage, | 13244 | message: *net.IncomingMessage, |
| 13222 | data_buffer: []u8, | 13245 | data_buffer: []u8, |
| 13223 | flags: net.ReceiveFlags, | 13246 | flags: net.ReceiveFlags, |
| 13224 | ) net.Socket.ReceiveError!void { | 13247 | nonblocking: bool, |
| | 13248 | ) (net.Socket.ReceiveError || error{WouldBlock})!void { |
| 13225 | // recvmmsg is useless, here's why: | 13249 | // recvmmsg is useless, here's why: |
| 13226 | // * [timeout bug](https://bugzilla.kernel.org/show_bug.cgi?id=75371) | 13250 | // * [timeout bug](https://bugzilla.kernel.org/show_bug.cgi?id=75371) |
| 13227 | // * it wants iovecs for each message but we have a better API: one data | 13251 | // * it wants iovecs for each message but we have a better API: one data |
| ... | @@ -13232,7 +13256,8 @@ fn netReceivePosix( | ... | @@ -13232,7 +13256,8 @@ fn netReceivePosix( |
| 13232 | @as(u32, if (flags.oob) posix.MSG.OOB else 0) | | 13256 | @as(u32, if (flags.oob) posix.MSG.OOB else 0) | |
| 13233 | @as(u32, if (flags.peek) posix.MSG.PEEK else 0) | | 13257 | @as(u32, if (flags.peek) posix.MSG.PEEK else 0) | |
| 13234 | @as(u32, if (flags.trunc) posix.MSG.TRUNC else 0) | | 13258 | @as(u32, if (flags.trunc) posix.MSG.TRUNC else 0) | |
| 13235 | posix.MSG.NOSIGNAL; | 13259 | posix.MSG.NOSIGNAL | |
| | 13260 | @as(u32, if (nonblocking) posix.MSG.DONTWAIT else 0); |
| 13236 | | 13261 | |
| 13237 | var storage: PosixAddress = undefined; | 13262 | var storage: PosixAddress = undefined; |
| 13238 | var iov: posix.iovec = .{ .base = data_buffer.ptr, .len = data_buffer.len }; | 13263 | var iov: posix.iovec = .{ .base = data_buffer.ptr, .len = data_buffer.len }; |
| ... | @@ -13280,7 +13305,7 @@ fn netReceivePosix( | ... | @@ -13280,7 +13305,7 @@ fn netReceivePosix( |
| 13280 | .PIPE => return syscall.fail(error.SocketUnconnected), | 13305 | .PIPE => return syscall.fail(error.SocketUnconnected), |
| 13281 | .CONNRESET => return syscall.fail(error.ConnectionResetByPeer), | 13306 | .CONNRESET => return syscall.fail(error.ConnectionResetByPeer), |
| 13282 | .NETDOWN => return syscall.fail(error.NetworkDown), | 13307 | .NETDOWN => return syscall.fail(error.NetworkDown), |
| 13283 | .AGAIN => |err| return syscall.errnoBug(err), | 13308 | .AGAIN => return syscall.fail(error.WouldBlock), |
| 13284 | .BADF => |err| return syscall.errnoBug(err), | 13309 | .BADF => |err| return syscall.errnoBug(err), |
| 13285 | .FAULT => |err| return syscall.errnoBug(err), | 13310 | .FAULT => |err| return syscall.errnoBug(err), |
| 13286 | .INVAL => |err| return syscall.errnoBug(err), | 13311 | .INVAL => |err| return syscall.errnoBug(err), |