mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 14:23:09 +00:00
Fix respondWebSocket, enable --webui on Windows
This commit re-enables the --webui functionality on windows, with the caveat that rebuild functionality is still disabled (due to deadlocks caused by reading to / writing from the same non-overlapped socket on multiple threads). I updated the UI to be aware of this, and hide the `Rebuild` button. http.Server: Remove incorrect advance() call. This was causing browsers to disconnect the websocket, as we were sending undefined bytes. build.WebServer: Re-enable on windows, but disable functionality that requires receiving messages from the client build-web: Show total times in tables
This commit is contained in:
parent
5f7a0bbabf
commit
125c4a265a
@ -105,6 +105,7 @@
|
|||||||
<th scope="col">Semantic Analysis</th>
|
<th scope="col">Semantic Analysis</th>
|
||||||
<th scope="col">Code Generation</th>
|
<th scope="col">Code Generation</th>
|
||||||
<th scope="col">Linking</th>
|
<th scope="col">Linking</th>
|
||||||
|
<th scope="col">Total</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<!-- HTML does not allow placing a 'slot' inside of a 'tbody' for backwards-compatibility
|
<!-- HTML does not allow placing a 'slot' inside of a 'tbody' for backwards-compatibility
|
||||||
@ -125,6 +126,7 @@
|
|||||||
<th scope="col">Semantic Analysis</th>
|
<th scope="col">Semantic Analysis</th>
|
||||||
<th scope="col">Code Generation</th>
|
<th scope="col">Code Generation</th>
|
||||||
<th scope="col">Linking</th>
|
<th scope="col">Linking</th>
|
||||||
|
<th scope="col">Total</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<!-- HTML does not allow placing a 'slot' inside of a 'tbody' for backwards-compatibility
|
<!-- HTML does not allow placing a 'slot' inside of a 'tbody' for backwards-compatibility
|
||||||
|
|||||||
@ -6,7 +6,7 @@ const domSummary = {
|
|||||||
stepCount: document.getElementById("summaryStepCount"),
|
stepCount: document.getElementById("summaryStepCount"),
|
||||||
status: document.getElementById("summaryStatus"),
|
status: document.getElementById("summaryStatus"),
|
||||||
};
|
};
|
||||||
const domButtonRebuild = document.getElementById("buttonRebuild");
|
let domButtonRebuild = document.getElementById("buttonRebuild");
|
||||||
const domStepList = document.getElementById("stepList");
|
const domStepList = document.getElementById("stepList");
|
||||||
let domSteps = [];
|
let domSteps = [];
|
||||||
|
|
||||||
@ -114,7 +114,13 @@ function hello(
|
|||||||
steps_len,
|
steps_len,
|
||||||
build_status,
|
build_status,
|
||||||
time_report,
|
time_report,
|
||||||
|
supports_recv,
|
||||||
) {
|
) {
|
||||||
|
if (!supports_recv && domButtonRebuild) {
|
||||||
|
domButtonRebuild.remove();
|
||||||
|
domButtonRebuild = null;
|
||||||
|
}
|
||||||
|
|
||||||
domSummary.stepCount.textContent = steps_len;
|
domSummary.stepCount.textContent = steps_len;
|
||||||
updateBuildStatus(build_status);
|
updateBuildStatus(build_status);
|
||||||
setConnectionStatus("", false);
|
setConnectionStatus("", false);
|
||||||
@ -161,12 +167,16 @@ function updateBuildStatus(s) {
|
|||||||
if (active) {
|
if (active) {
|
||||||
domSummary.status.classList.add("status-running");
|
domSummary.status.classList.add("status-running");
|
||||||
domSummary.status.classList.remove("status-idle");
|
domSummary.status.classList.remove("status-idle");
|
||||||
|
if (domButtonRebuild) {
|
||||||
domButtonRebuild.disabled = true;
|
domButtonRebuild.disabled = true;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
domSummary.status.classList.remove("status-running");
|
domSummary.status.classList.remove("status-running");
|
||||||
domSummary.status.classList.add("status-idle");
|
domSummary.status.classList.add("status-idle");
|
||||||
|
if (domButtonRebuild) {
|
||||||
domButtonRebuild.disabled = false;
|
domButtonRebuild.disabled = false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (reset_time_reports) {
|
if (reset_time_reports) {
|
||||||
// Grey out and collapse all the time reports
|
// Grey out and collapse all the time reports
|
||||||
for (const time_report_host of domTimeReportList.children) {
|
for (const time_report_host of domTimeReportList.children) {
|
||||||
|
|||||||
@ -30,6 +30,7 @@ const js = struct {
|
|||||||
steps_len: u32,
|
steps_len: u32,
|
||||||
status: abi.BuildStatus,
|
status: abi.BuildStatus,
|
||||||
time_report: bool,
|
time_report: bool,
|
||||||
|
supports_recv: bool,
|
||||||
) void;
|
) void;
|
||||||
extern "core" fn updateBuildStatus(status: abi.BuildStatus) void;
|
extern "core" fn updateBuildStatus(status: abi.BuildStatus) void;
|
||||||
extern "core" fn updateStepStatus(step_idx: u32) void;
|
extern "core" fn updateStepStatus(step_idx: u32) void;
|
||||||
@ -160,7 +161,7 @@ fn helloMessage(msg_bytes: []align(4) u8) Allocator.Error!void {
|
|||||||
step_list = steps;
|
step_list = steps;
|
||||||
step_list_data = duped_step_name_data;
|
step_list_data = duped_step_name_data;
|
||||||
|
|
||||||
js.hello(step_list.len, hdr.status, hdr.flags.time_report);
|
js.hello(step_list.len, hdr.status, hdr.flags.time_report, hdr.flags.supports_recv);
|
||||||
}
|
}
|
||||||
fn statusUpdateMessage(msg_bytes: []u8) Allocator.Error!void {
|
fn statusUpdateMessage(msg_bytes: []u8) Allocator.Error!void {
|
||||||
if (msg_bytes.len < @sizeOf(abi.StatusUpdate)) @panic("malformed StatusUpdate message");
|
if (msg_bytes.len < @sizeOf(abi.StatusUpdate)) @panic("malformed StatusUpdate message");
|
||||||
|
|||||||
@ -175,6 +175,7 @@ pub fn compileResultMessage(msg_bytes: []u8) error{OutOfMemory}!void {
|
|||||||
\\ <td>{D}</td>
|
\\ <td>{D}</td>
|
||||||
\\ <td>{D}</td>
|
\\ <td>{D}</td>
|
||||||
\\ <td>{D}</td>
|
\\ <td>{D}</td>
|
||||||
|
\\ <td>{D}</td>
|
||||||
\\</tr>
|
\\</tr>
|
||||||
\\
|
\\
|
||||||
, .{
|
, .{
|
||||||
@ -182,6 +183,7 @@ pub fn compileResultMessage(msg_bytes: []u8) error{OutOfMemory}!void {
|
|||||||
file.ns_sema,
|
file.ns_sema,
|
||||||
file.ns_codegen,
|
file.ns_codegen,
|
||||||
file.ns_link,
|
file.ns_link,
|
||||||
|
file.ns_sema + file.ns_codegen + file.ns_link,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (slowest_files.len > max_table_rows) {
|
if (slowest_files.len > max_table_rows) {
|
||||||
@ -203,6 +205,7 @@ pub fn compileResultMessage(msg_bytes: []u8) error{OutOfMemory}!void {
|
|||||||
\\ <td>{D}</td>
|
\\ <td>{D}</td>
|
||||||
\\ <td>{D}</td>
|
\\ <td>{D}</td>
|
||||||
\\ <td>{D}</td>
|
\\ <td>{D}</td>
|
||||||
|
\\ <td>{D}</td>
|
||||||
\\</tr>
|
\\</tr>
|
||||||
\\
|
\\
|
||||||
, .{
|
, .{
|
||||||
@ -212,6 +215,7 @@ pub fn compileResultMessage(msg_bytes: []u8) error{OutOfMemory}!void {
|
|||||||
decl.ns_sema,
|
decl.ns_sema,
|
||||||
decl.ns_codegen,
|
decl.ns_codegen,
|
||||||
decl.ns_link,
|
decl.ns_link,
|
||||||
|
decl.ns_sema + decl.ns_codegen + decl.ns_link,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (slowest_decls.len > max_table_rows) {
|
if (slowest_decls.len > max_table_rows) {
|
||||||
|
|||||||
@ -65,16 +65,6 @@ pub fn init(opts: Options) WebServer {
|
|||||||
std.process.fatal("--webui not yet implemented for single-threaded builds", .{});
|
std.process.fatal("--webui not yet implemented for single-threaded builds", .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (builtin.os.tag == .windows) {
|
|
||||||
// At the time of writing, there are two bugs in the standard library which break this feature on Windows:
|
|
||||||
// * Reading from a socket on one thread while writing to it on another seems to deadlock.
|
|
||||||
// * Vectored writes to sockets currently trigger an infinite loop when a buffer has length 0.
|
|
||||||
//
|
|
||||||
// Both of these bugs are expected to be solved by changes which are currently in the unmerged
|
|
||||||
// 'wrangle-writer-buffering' branch. Until that makes it in, this must remain disabled.
|
|
||||||
std.process.fatal("--webui is currently disabled on Windows due to bugs", .{});
|
|
||||||
}
|
|
||||||
|
|
||||||
const all_steps = opts.all_steps;
|
const all_steps = opts.all_steps;
|
||||||
|
|
||||||
const step_names_trailing = opts.gpa.alloc(u8, len: {
|
const step_names_trailing = opts.gpa.alloc(u8, len: {
|
||||||
@ -297,13 +287,20 @@ fn serveWebSocket(ws: *WebServer, sock: *http.Server.WebSocket) !noreturn {
|
|||||||
copy.* = @atomicLoad(u8, shared, .monotonic);
|
copy.* = @atomicLoad(u8, shared, .monotonic);
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = try std.Thread.spawn(.{}, recvWebSocketMessages, .{ ws, sock });
|
// Calling WSARecvFrom on one thread while another calls WSASend deadlocks.
|
||||||
|
// This functionality is disabled until std.net uses overlapped sockets on Windows.
|
||||||
|
const supports_recv = builtin.os.tag != .windows;
|
||||||
|
const recv_thread = if (supports_recv)
|
||||||
|
try std.Thread.spawn(.{}, recvWebSocketMessages, .{ ws, sock })
|
||||||
|
else {};
|
||||||
|
defer if (supports_recv) recv_thread.join();
|
||||||
|
|
||||||
{
|
{
|
||||||
const hello_header: abi.Hello = .{
|
const hello_header: abi.Hello = .{
|
||||||
.status = prev_build_status,
|
.status = prev_build_status,
|
||||||
.flags = .{
|
.flags = .{
|
||||||
.time_report = ws.graph.time_report,
|
.time_report = ws.graph.time_report,
|
||||||
|
.supports_recv = supports_recv,
|
||||||
},
|
},
|
||||||
.timestamp = ws.now(),
|
.timestamp = ws.now(),
|
||||||
.steps_len = @intCast(ws.all_steps.len),
|
.steps_len = @intCast(ws.all_steps.len),
|
||||||
|
|||||||
@ -103,7 +103,9 @@ pub const Hello = extern struct {
|
|||||||
pub const Flags = packed struct(u16) {
|
pub const Flags = packed struct(u16) {
|
||||||
/// Whether time reporting is enabled.
|
/// Whether time reporting is enabled.
|
||||||
time_report: bool,
|
time_report: bool,
|
||||||
_: u15 = 0,
|
/// If this platform supports receiving messages from the client
|
||||||
|
supports_recv: bool,
|
||||||
|
_: u14 = 0,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
/// WebSocket server->client.
|
/// WebSocket server->client.
|
||||||
|
|||||||
@ -546,7 +546,6 @@ pub const Request = struct {
|
|||||||
try out.writeAll("connection: upgrade\r\nupgrade: websocket\r\nsec-websocket-accept: ");
|
try out.writeAll("connection: upgrade\r\nupgrade: websocket\r\nsec-websocket-accept: ");
|
||||||
const base64_digest = try out.writableArray(28);
|
const base64_digest = try out.writableArray(28);
|
||||||
assert(std.base64.standard.Encoder.encode(base64_digest, &digest).len == base64_digest.len);
|
assert(std.base64.standard.Encoder.encode(base64_digest, &digest).len == base64_digest.len);
|
||||||
out.advance(base64_digest.len);
|
|
||||||
try out.writeAll("\r\n");
|
try out.writeAll("\r\n");
|
||||||
|
|
||||||
for (options.extra_headers) |header| {
|
for (options.extra_headers) |header| {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user