| author | |
| committer | |
| log | 95f57c3369181123aa7ebd4a9654fc489f8bb4fd |
| tree | 4faf083d4cc96f9ce732d91c5f280744ba986d17 |
| parent | 125c4a265aa7cfe82b3fc0c1ac7de75a07315411 |
build-web: Remove the now-redundant supports_recv logic6 files changed, 74 insertions(+), 43 deletions(-)
lib/build-web/main.js+3-13| ... | @@ -6,7 +6,7 @@ const domSummary = { | ... | @@ -6,7 +6,7 @@ const domSummary = { |
| 6 | stepCount: document.getElementById("summaryStepCount"), | 6 | stepCount: document.getElementById("summaryStepCount"), |
| 7 | status: document.getElementById("summaryStatus"), | 7 | status: document.getElementById("summaryStatus"), |
| 8 | }; | 8 | }; |
| 9 | let domButtonRebuild = document.getElementById("buttonRebuild"); | 9 | const domButtonRebuild = document.getElementById("buttonRebuild"); |
| 10 | const domStepList = document.getElementById("stepList"); | 10 | const domStepList = document.getElementById("stepList"); |
| 11 | let domSteps = []; | 11 | let domSteps = []; |
| 12 | 12 | ||
| ... | @@ -114,13 +114,7 @@ function hello( | ... | @@ -114,13 +114,7 @@ function hello( |
| 114 | steps_len, | 114 | steps_len, |
| 115 | build_status, | 115 | build_status, |
| 116 | time_report, | 116 | time_report, |
| 117 | supports_recv, | ||
| 118 | ) { | 117 | ) { |
| 119 | if (!supports_recv && domButtonRebuild) { | ||
| 120 | domButtonRebuild.remove(); | ||
| 121 | domButtonRebuild = null; | ||
| 122 | } | ||
| 123 | |||
| 124 | domSummary.stepCount.textContent = steps_len; | 118 | domSummary.stepCount.textContent = steps_len; |
| 125 | updateBuildStatus(build_status); | 119 | updateBuildStatus(build_status); |
| 126 | setConnectionStatus("", false); | 120 | setConnectionStatus("", false); |
| ... | @@ -167,15 +161,11 @@ function updateBuildStatus(s) { | ... | @@ -167,15 +161,11 @@ function updateBuildStatus(s) { |
| 167 | if (active) { | 161 | if (active) { |
| 168 | domSummary.status.classList.add("status-running"); | 162 | domSummary.status.classList.add("status-running"); |
| 169 | domSummary.status.classList.remove("status-idle"); | 163 | domSummary.status.classList.remove("status-idle"); |
| 170 | if (domButtonRebuild) { | 164 | domButtonRebuild.disabled = true; |
| 171 | domButtonRebuild.disabled = true; | ||
| 172 | } | ||
| 173 | } else { | 165 | } else { |
| 174 | domSummary.status.classList.remove("status-running"); | 166 | domSummary.status.classList.remove("status-running"); |
| 175 | domSummary.status.classList.add("status-idle"); | 167 | domSummary.status.classList.add("status-idle"); |
| 176 | if (domButtonRebuild) { | 168 | domButtonRebuild.disabled = false; |
| 177 | domButtonRebuild.disabled = false; | ||
| 178 | } | ||
| 179 | } | 169 | } |
| 180 | if (reset_time_reports) { | 170 | if (reset_time_reports) { |
| 181 | // Grey out and collapse all the time reports | 171 | // Grey out and collapse all the time reports |
lib/build-web/main.zig+1-2| ... | @@ -30,7 +30,6 @@ const js = struct { | ... | @@ -30,7 +30,6 @@ const js = struct { |
| 30 | steps_len: u32, | 30 | steps_len: u32, |
| 31 | status: abi.BuildStatus, | 31 | status: abi.BuildStatus, |
| 32 | time_report: bool, | 32 | time_report: bool, |
| 33 | supports_recv: bool, | ||
| 34 | ) void; | 33 | ) void; |
| 35 | extern "core" fn updateBuildStatus(status: abi.BuildStatus) void; | 34 | extern "core" fn updateBuildStatus(status: abi.BuildStatus) void; |
| 36 | extern "core" fn updateStepStatus(step_idx: u32) void; | 35 | extern "core" fn updateStepStatus(step_idx: u32) void; |
| ... | @@ -161,7 +160,7 @@ fn helloMessage(msg_bytes: []align(4) u8) Allocator.Error!void { | ... | @@ -161,7 +160,7 @@ fn helloMessage(msg_bytes: []align(4) u8) Allocator.Error!void { |
| 161 | step_list = steps; | 160 | step_list = steps; |
| 162 | step_list_data = duped_step_name_data; | 161 | step_list_data = duped_step_name_data; |
| 163 | 162 | ||
| 164 | js.hello(step_list.len, hdr.status, hdr.flags.time_report, hdr.flags.supports_recv); | 163 | js.hello(step_list.len, hdr.status, hdr.flags.time_report); |
| 165 | } | 164 | } |
| 166 | fn statusUpdateMessage(msg_bytes: []u8) Allocator.Error!void { | 165 | fn statusUpdateMessage(msg_bytes: []u8) Allocator.Error!void { |
| 167 | if (msg_bytes.len < @sizeOf(abi.StatusUpdate)) @panic("malformed StatusUpdate message"); | 166 | if (msg_bytes.len < @sizeOf(abi.StatusUpdate)) @panic("malformed StatusUpdate message"); |
lib/std/Build/WebServer.zig+2-8| ... | @@ -287,20 +287,14 @@ fn serveWebSocket(ws: *WebServer, sock: *http.Server.WebSocket) !noreturn { | ... | @@ -287,20 +287,14 @@ fn serveWebSocket(ws: *WebServer, sock: *http.Server.WebSocket) !noreturn { |
| 287 | copy.* = @atomicLoad(u8, shared, .monotonic); | 287 | copy.* = @atomicLoad(u8, shared, .monotonic); |
| 288 | } | 288 | } |
| 289 | 289 | ||
| 290 | // Calling WSARecvFrom on one thread while another calls WSASend deadlocks. | 290 | const recv_thread = try std.Thread.spawn(.{}, recvWebSocketMessages, .{ ws, sock }); |
| 291 | // This functionality is disabled until std.net uses overlapped sockets on Windows. | 291 | defer recv_thread.join(); |
| 292 | const supports_recv = builtin.os.tag != .windows; | ||
| 293 | const recv_thread = if (supports_recv) | ||
| 294 | try std.Thread.spawn(.{}, recvWebSocketMessages, .{ ws, sock }) | ||
| 295 | else {}; | ||
| 296 | defer if (supports_recv) recv_thread.join(); | ||
| 297 | 292 | ||
| 298 | { | 293 | { |
| 299 | const hello_header: abi.Hello = .{ | 294 | const hello_header: abi.Hello = .{ |
| 300 | .status = prev_build_status, | 295 | .status = prev_build_status, |
| 301 | .flags = .{ | 296 | .flags = .{ |
| 302 | .time_report = ws.graph.time_report, | 297 | .time_report = ws.graph.time_report, |
| 303 | .supports_recv = supports_recv, | ||
| 304 | }, | 298 | }, |
| 305 | .timestamp = ws.now(), | 299 | .timestamp = ws.now(), |
| 306 | .steps_len = @intCast(ws.all_steps.len), | 300 | .steps_len = @intCast(ws.all_steps.len), |
lib/std/Build/abi.zig+1-3| ... | @@ -103,9 +103,7 @@ pub const Hello = extern struct { | ... | @@ -103,9 +103,7 @@ pub const Hello = extern struct { |
| 103 | pub const Flags = packed struct(u16) { | 103 | pub const Flags = packed struct(u16) { |
| 104 | /// Whether time reporting is enabled. | 104 | /// Whether time reporting is enabled. |
| 105 | time_report: bool, | 105 | time_report: bool, |
| 106 | /// If this platform supports receiving messages from the client | 106 | _: u15 = 0, |
| 107 | supports_recv: bool, | ||
| 108 | _: u14 = 0, | ||
| 109 | }; | 107 | }; |
| 110 | }; | 108 | }; |
| 111 | /// WebSocket server->client. | 109 | /// WebSocket server->client. |
lib/std/net.zig+63-11| ... | @@ -259,6 +259,7 @@ pub const Address = extern union { | ... | @@ -259,6 +259,7 @@ pub const Address = extern union { |
| 259 | /// Sets SO_REUSEADDR and SO_REUSEPORT on POSIX. | 259 | /// Sets SO_REUSEADDR and SO_REUSEPORT on POSIX. |
| 260 | /// Sets SO_REUSEADDR on Windows, which is roughly equivalent. | 260 | /// Sets SO_REUSEADDR on Windows, which is roughly equivalent. |
| 261 | reuse_address: bool = false, | 261 | reuse_address: bool = false, |
| 262 | /// Sets O_NONBLOCK. | ||
| 262 | force_nonblocking: bool = false, | 263 | force_nonblocking: bool = false, |
| 263 | }; | 264 | }; |
| 264 | 265 | ||
| ... | @@ -1998,11 +1999,8 @@ pub const Stream = struct { | ... | @@ -1998,11 +1999,8 @@ pub const Stream = struct { |
| 1998 | return n; | 1999 | return n; |
| 1999 | } | 2000 | } |
| 2000 | 2001 | ||
| 2001 | fn streamBufs(r: *Reader, bufs: []windows.ws2_32.WSABUF) Error!u32 { | 2002 | fn handleRecvError(winsock_error: windows.ws2_32.WinsockError) Error!void { |
| 2002 | var n: u32 = undefined; | 2003 | switch (winsock_error) { |
| 2003 | var flags: u32 = 0; | ||
| 2004 | const rc = windows.ws2_32.WSARecvFrom(r.net_stream.handle, bufs.ptr, @intCast(bufs.len), &n, &flags, null, null, null, null); | ||
| 2005 | if (rc != 0) switch (windows.ws2_32.WSAGetLastError()) { | ||
| 2006 | .WSAECONNRESET => return error.ConnectionResetByPeer, | 2004 | .WSAECONNRESET => return error.ConnectionResetByPeer, |
| 2007 | .WSAEFAULT => unreachable, // a pointer is not completely contained in user address space. | 2005 | .WSAEFAULT => unreachable, // a pointer is not completely contained in user address space. |
| 2008 | .WSAEINPROGRESS, .WSAEINTR => unreachable, // deprecated and removed in WSA 2.2 | 2006 | .WSAEINPROGRESS, .WSAEINTR => unreachable, // deprecated and removed in WSA 2.2 |
| ... | @@ -2013,10 +2011,39 @@ pub const Stream = struct { | ... | @@ -2013,10 +2011,39 @@ pub const Stream = struct { |
| 2013 | .WSAENOTCONN => return error.SocketNotConnected, | 2011 | .WSAENOTCONN => return error.SocketNotConnected, |
| 2014 | .WSAEWOULDBLOCK => return error.WouldBlock, | 2012 | .WSAEWOULDBLOCK => return error.WouldBlock, |
| 2015 | .WSANOTINITIALISED => unreachable, // WSAStartup must be called before this function | 2013 | .WSANOTINITIALISED => unreachable, // WSAStartup must be called before this function |
| 2016 | .WSA_IO_PENDING => unreachable, // not using overlapped I/O | 2014 | .WSA_IO_PENDING => unreachable, |
| 2017 | .WSA_OPERATION_ABORTED => unreachable, // not using overlapped I/O | 2015 | .WSA_OPERATION_ABORTED => unreachable, // not using overlapped I/O |
| 2018 | else => |err| return windows.unexpectedWSAError(err), | 2016 | else => |err| return windows.unexpectedWSAError(err), |
| 2017 | } | ||
| 2018 | } | ||
| 2019 | |||
| 2020 | fn streamBufs(r: *Reader, bufs: []windows.ws2_32.WSABUF) Error!u32 { | ||
| 2021 | var flags: u32 = 0; | ||
| 2022 | var overlapped: windows.OVERLAPPED = std.mem.zeroes(windows.OVERLAPPED); | ||
| 2023 | |||
| 2024 | var n: u32 = undefined; | ||
| 2025 | if (windows.ws2_32.WSARecv( | ||
| 2026 | r.net_stream.handle, | ||
| 2027 | bufs.ptr, | ||
| 2028 | @intCast(bufs.len), | ||
| 2029 | &n, | ||
| 2030 | &flags, | ||
| 2031 | &overlapped, | ||
| 2032 | null, | ||
| 2033 | ) == windows.ws2_32.SOCKET_ERROR) switch (windows.ws2_32.WSAGetLastError()) { | ||
| 2034 | .WSA_IO_PENDING => { | ||
| 2035 | var result_flags: u32 = undefined; | ||
| 2036 | if (windows.ws2_32.WSAGetOverlappedResult( | ||
| 2037 | r.net_stream.handle, | ||
| 2038 | &overlapped, | ||
| 2039 | &n, | ||
| 2040 | windows.TRUE, | ||
| 2041 | &result_flags, | ||
| 2042 | ) == windows.FALSE) try handleRecvError(windows.ws2_32.WSAGetLastError()); | ||
| 2043 | }, | ||
| 2044 | else => |winsock_error| try handleRecvError(winsock_error), | ||
| 2019 | }; | 2045 | }; |
| 2046 | |||
| 2020 | return n; | 2047 | return n; |
| 2021 | } | 2048 | } |
| 2022 | }, | 2049 | }, |
| ... | @@ -2136,10 +2163,8 @@ pub const Stream = struct { | ... | @@ -2136,10 +2163,8 @@ pub const Stream = struct { |
| 2136 | return io_w.consume(n); | 2163 | return io_w.consume(n); |
| 2137 | } | 2164 | } |
| 2138 | 2165 | ||
| 2139 | fn sendBufs(handle: Stream.Handle, bufs: []windows.ws2_32.WSABUF) Error!u32 { | 2166 | fn handleSendError(winsock_error: windows.ws2_32.WinsockError) Error!void { |
| 2140 | var n: u32 = undefined; | 2167 | switch (winsock_error) { |
| 2141 | const rc = windows.ws2_32.WSASend(handle, bufs.ptr, @intCast(bufs.len), &n, 0, null, null); | ||
| 2142 | if (rc == windows.ws2_32.SOCKET_ERROR) switch (windows.ws2_32.WSAGetLastError()) { | ||
| 2143 | .WSAECONNABORTED => return error.ConnectionResetByPeer, | 2168 | .WSAECONNABORTED => return error.ConnectionResetByPeer, |
| 2144 | .WSAECONNRESET => return error.ConnectionResetByPeer, | 2169 | .WSAECONNRESET => return error.ConnectionResetByPeer, |
| 2145 | .WSAEFAULT => unreachable, // a pointer is not completely contained in user address space. | 2170 | .WSAEFAULT => unreachable, // a pointer is not completely contained in user address space. |
| ... | @@ -2155,10 +2180,37 @@ pub const Stream = struct { | ... | @@ -2155,10 +2180,37 @@ pub const Stream = struct { |
| 2155 | .WSAESHUTDOWN => unreachable, // cannot send on a socket after write shutdown | 2180 | .WSAESHUTDOWN => unreachable, // cannot send on a socket after write shutdown |
| 2156 | .WSAEWOULDBLOCK => return error.WouldBlock, | 2181 | .WSAEWOULDBLOCK => return error.WouldBlock, |
| 2157 | .WSANOTINITIALISED => unreachable, // WSAStartup must be called before this function | 2182 | .WSANOTINITIALISED => unreachable, // WSAStartup must be called before this function |
| 2158 | .WSA_IO_PENDING => unreachable, // not using overlapped I/O | 2183 | .WSA_IO_PENDING => unreachable, |
| 2159 | .WSA_OPERATION_ABORTED => unreachable, // not using overlapped I/O | 2184 | .WSA_OPERATION_ABORTED => unreachable, // not using overlapped I/O |
| 2160 | else => |err| return windows.unexpectedWSAError(err), | 2185 | else => |err| return windows.unexpectedWSAError(err), |
| 2186 | } | ||
| 2187 | } | ||
| 2188 | |||
| 2189 | fn sendBufs(handle: Stream.Handle, bufs: []windows.ws2_32.WSABUF) Error!u32 { | ||
| 2190 | var n: u32 = undefined; | ||
| 2191 | var overlapped: windows.OVERLAPPED = std.mem.zeroes(windows.OVERLAPPED); | ||
| 2192 | if (windows.ws2_32.WSASend( | ||
| 2193 | handle, | ||
| 2194 | bufs.ptr, | ||
| 2195 | @intCast(bufs.len), | ||
| 2196 | &n, | ||
| 2197 | 0, | ||
| 2198 | &overlapped, | ||
| 2199 | null, | ||
| 2200 | ) == windows.ws2_32.SOCKET_ERROR) switch (windows.ws2_32.WSAGetLastError()) { | ||
| 2201 | .WSA_IO_PENDING => { | ||
| 2202 | var result_flags: u32 = undefined; | ||
| 2203 | if (windows.ws2_32.WSAGetOverlappedResult( | ||
| 2204 | handle, | ||
| 2205 | &overlapped, | ||
| 2206 | &n, | ||
| 2207 | windows.TRUE, | ||
| 2208 | &result_flags, | ||
| 2209 | ) == windows.FALSE) try handleSendError(windows.ws2_32.WSAGetLastError()); | ||
| 2210 | }, | ||
| 2211 | else => |winsock_error| try handleSendError(winsock_error), | ||
| 2161 | }; | 2212 | }; |
| 2213 | |||
| 2162 | return n; | 2214 | return n; |
| 2163 | } | 2215 | } |
| 2164 | }, | 2216 | }, |
lib/std/posix.zig+4-6| ... | @@ -3615,13 +3615,11 @@ pub const SocketError = error{ | ... | @@ -3615,13 +3615,11 @@ pub const SocketError = error{ |
| 3615 | 3615 | ||
| 3616 | pub fn socket(domain: u32, socket_type: u32, protocol: u32) SocketError!socket_t { | 3616 | pub fn socket(domain: u32, socket_type: u32, protocol: u32) SocketError!socket_t { |
| 3617 | if (native_os == .windows) { | 3617 | if (native_os == .windows) { |
| 3618 | // NOTE: windows translates the SOCK.NONBLOCK/SOCK.CLOEXEC flags into | 3618 | // These flags are not actually part of the Windows API, instead they are converted here for compatibility |
| 3619 | // windows-analogous operations | ||
| 3620 | const filtered_sock_type = socket_type & ~@as(u32, SOCK.NONBLOCK | SOCK.CLOEXEC); | 3619 | const filtered_sock_type = socket_type & ~@as(u32, SOCK.NONBLOCK | SOCK.CLOEXEC); |
| 3621 | const flags: u32 = if ((socket_type & SOCK.CLOEXEC) != 0) | 3620 | var flags: u32 = windows.ws2_32.WSA_FLAG_OVERLAPPED; |
| 3622 | windows.ws2_32.WSA_FLAG_NO_HANDLE_INHERIT | 3621 | if ((socket_type & SOCK.CLOEXEC) != 0) flags |= windows.ws2_32.WSA_FLAG_NO_HANDLE_INHERIT; |
| 3623 | else | 3622 | |
| 3624 | 0; | ||
| 3625 | const rc = try windows.WSASocketW( | 3623 | const rc = try windows.WSASocketW( |
| 3626 | @bitCast(domain), | 3624 | @bitCast(domain), |
| 3627 | @bitCast(filtered_sock_type), | 3625 | @bitCast(filtered_sock_type), |