authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2026-09-19 04:50:31-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2026-09-26 19:08:50-04:00
logfbe1bbf662e339dd5f3bc01c83d236d867726854
tree61b7eb271e0804daf0b5ae62d404e96494b15f44
parent488c15320b6e2848dd61245303e75f7577313ff2

runner: make test runs deterministic


8 files changed, 181 insertions(+), 211 deletions(-)

test/incremental2/change_panic_handler_explicit/0-main.zig deleted-46
......@@ -1,46 +0,0 @@
1pub fn main() !u8 {
2 var a: u8 = undefined;
3 a = 255;
4 _ = a + 1;
5 return 1;
6}
7const no_panic = std.debug.no_panic;
8pub const panic = struct {
9 pub const call = myPanic;
10 pub fn integerOverflow() noreturn {
11 @panic("integer overflow");
12 }
13 pub const sentinelMismatch = no_panic.sentinelMismatch;
14 pub const unwrapError = no_panic.unwrapError;
15 pub const outOfBounds = no_panic.outOfBounds;
16 pub const startGreaterThanEnd = no_panic.startGreaterThanEnd;
17 pub const inactiveUnionField = no_panic.inactiveUnionField;
18 pub const sliceCastLenRemainder = no_panic.sliceCastLenRemainder;
19 pub const reachedUnreachable = no_panic.reachedUnreachable;
20 pub const unwrapNull = no_panic.unwrapNull;
21 pub const castToNull = no_panic.castToNull;
22 pub const incorrectAlignment = no_panic.incorrectAlignment;
23 pub const invalidErrorCode = no_panic.invalidErrorCode;
24 pub const unexpectedErrorCode = no_panic.unexpectedErrorCode;
25 pub const integerOutOfBounds = no_panic.integerOutOfBounds;
26 pub const shlOverflow = no_panic.shlOverflow;
27 pub const shrOverflow = no_panic.shrOverflow;
28 pub const divideByZero = no_panic.divideByZero;
29 pub const exactDivisionRemainder = no_panic.exactDivisionRemainder;
30 pub const integerPartOutOfBounds = no_panic.integerPartOutOfBounds;
31 pub const corruptSwitch = no_panic.corruptSwitch;
32 pub const shiftRhsTooBig = no_panic.shiftRhsTooBig;
33 pub const invalidEnumValue = no_panic.invalidEnumValue;
34 pub const forLenMismatch = no_panic.forLenMismatch;
35 pub const copyLenMismatch = no_panic.copyLenMismatch;
36 pub const memcpyAlias = no_panic.memcpyAlias;
37 pub const noreturnReturned = no_panic.noreturnReturned;
38 pub const loadUninstantiableType = no_panic.loadUninstantiableType;
39};
40fn myPanic(msg: []const u8, _: ?usize) noreturn {
41 var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{});
42 stdout_writer.interface.print("panic message: {s}\n", .{msg}) catch {};
43 std.process.exit(0);
44}
45const std = @import("std");
46const io = std.Io.Threaded.global_single_threaded.io();
test/incremental2/change_panic_handler_explicit/0/main.zig created+46
......@@ -0,0 +1,46 @@
1pub fn main() !u8 {
2 var a: u8 = undefined;
3 a = 255;
4 _ = a + 1;
5 return 1;
6}
7const no_panic = std.debug.no_panic;
8pub const panic = struct {
9 pub const call = myPanic;
10 pub fn integerOverflow() noreturn {
11 @panic("integer overflow");
12 }
13 pub const sentinelMismatch = no_panic.sentinelMismatch;
14 pub const unwrapError = no_panic.unwrapError;
15 pub const outOfBounds = no_panic.outOfBounds;
16 pub const startGreaterThanEnd = no_panic.startGreaterThanEnd;
17 pub const inactiveUnionField = no_panic.inactiveUnionField;
18 pub const sliceCastLenRemainder = no_panic.sliceCastLenRemainder;
19 pub const reachedUnreachable = no_panic.reachedUnreachable;
20 pub const unwrapNull = no_panic.unwrapNull;
21 pub const castToNull = no_panic.castToNull;
22 pub const incorrectAlignment = no_panic.incorrectAlignment;
23 pub const invalidErrorCode = no_panic.invalidErrorCode;
24 pub const unexpectedErrorCode = no_panic.unexpectedErrorCode;
25 pub const integerOutOfBounds = no_panic.integerOutOfBounds;
26 pub const shlOverflow = no_panic.shlOverflow;
27 pub const shrOverflow = no_panic.shrOverflow;
28 pub const divideByZero = no_panic.divideByZero;
29 pub const exactDivisionRemainder = no_panic.exactDivisionRemainder;
30 pub const integerPartOutOfBounds = no_panic.integerPartOutOfBounds;
31 pub const corruptSwitch = no_panic.corruptSwitch;
32 pub const shiftRhsTooBig = no_panic.shiftRhsTooBig;
33 pub const invalidEnumValue = no_panic.invalidEnumValue;
34 pub const forLenMismatch = no_panic.forLenMismatch;
35 pub const copyLenMismatch = no_panic.copyLenMismatch;
36 pub const memcpyAlias = no_panic.memcpyAlias;
37 pub const noreturnReturned = no_panic.noreturnReturned;
38 pub const loadUninstantiableType = no_panic.loadUninstantiableType;
39};
40fn myPanic(msg: []const u8, _: ?usize) noreturn {
41 var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{});
42 stdout_writer.interface.print("panic message: {s}\n", .{msg}) catch {};
43 std.process.exit(0);
44}
45const std = @import("std");
46const io = std.Io.Threaded.global_single_threaded.io();
test/incremental2/change_panic_handler_explicit/1-main.zig deleted-46
......@@ -1,46 +0,0 @@
1pub fn main() !u8 {
2 var a: u8 = undefined;
3 a = 255;
4 _ = a + 1;
5 return 1;
6}
7const no_panic = std.debug.no_panic;
8pub const panic = struct {
9 pub const call = myPanic;
10 pub fn integerOverflow() noreturn {
11 @panic("integer overflow");
12 }
13 pub const sentinelMismatch = no_panic.sentinelMismatch;
14 pub const unwrapError = no_panic.unwrapError;
15 pub const outOfBounds = no_panic.outOfBounds;
16 pub const startGreaterThanEnd = no_panic.startGreaterThanEnd;
17 pub const inactiveUnionField = no_panic.inactiveUnionField;
18 pub const sliceCastLenRemainder = no_panic.sliceCastLenRemainder;
19 pub const reachedUnreachable = no_panic.reachedUnreachable;
20 pub const unwrapNull = no_panic.unwrapNull;
21 pub const castToNull = no_panic.castToNull;
22 pub const incorrectAlignment = no_panic.incorrectAlignment;
23 pub const invalidErrorCode = no_panic.invalidErrorCode;
24 pub const unexpectedErrorCode = no_panic.unexpectedErrorCode;
25 pub const integerOutOfBounds = no_panic.integerOutOfBounds;
26 pub const shlOverflow = no_panic.shlOverflow;
27 pub const shrOverflow = no_panic.shrOverflow;
28 pub const divideByZero = no_panic.divideByZero;
29 pub const exactDivisionRemainder = no_panic.exactDivisionRemainder;
30 pub const integerPartOutOfBounds = no_panic.integerPartOutOfBounds;
31 pub const corruptSwitch = no_panic.corruptSwitch;
32 pub const shiftRhsTooBig = no_panic.shiftRhsTooBig;
33 pub const invalidEnumValue = no_panic.invalidEnumValue;
34 pub const forLenMismatch = no_panic.forLenMismatch;
35 pub const copyLenMismatch = no_panic.copyLenMismatch;
36 pub const memcpyAlias = no_panic.memcpyAlias;
37 pub const noreturnReturned = no_panic.noreturnReturned;
38 pub const loadUninstantiableType = no_panic.loadUninstantiableType;
39};
40fn myPanic(msg: []const u8, _: ?usize) noreturn {
41 var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{});
42 stdout_writer.interface.print("new panic message: {s}\n", .{msg}) catch {};
43 std.process.exit(0);
44}
45const std = @import("std");
46const io = std.Io.Threaded.global_single_threaded.io();
test/incremental2/change_panic_handler_explicit/1/main.zig created+46
......@@ -0,0 +1,46 @@
1pub fn main() !u8 {
2 var a: u8 = undefined;
3 a = 255;
4 _ = a + 1;
5 return 1;
6}
7const no_panic = std.debug.no_panic;
8pub const panic = struct {
9 pub const call = myPanic;
10 pub fn integerOverflow() noreturn {
11 @panic("integer overflow");
12 }
13 pub const sentinelMismatch = no_panic.sentinelMismatch;
14 pub const unwrapError = no_panic.unwrapError;
15 pub const outOfBounds = no_panic.outOfBounds;
16 pub const startGreaterThanEnd = no_panic.startGreaterThanEnd;
17 pub const inactiveUnionField = no_panic.inactiveUnionField;
18 pub const sliceCastLenRemainder = no_panic.sliceCastLenRemainder;
19 pub const reachedUnreachable = no_panic.reachedUnreachable;
20 pub const unwrapNull = no_panic.unwrapNull;
21 pub const castToNull = no_panic.castToNull;
22 pub const incorrectAlignment = no_panic.incorrectAlignment;
23 pub const invalidErrorCode = no_panic.invalidErrorCode;
24 pub const unexpectedErrorCode = no_panic.unexpectedErrorCode;
25 pub const integerOutOfBounds = no_panic.integerOutOfBounds;
26 pub const shlOverflow = no_panic.shlOverflow;
27 pub const shrOverflow = no_panic.shrOverflow;
28 pub const divideByZero = no_panic.divideByZero;
29 pub const exactDivisionRemainder = no_panic.exactDivisionRemainder;
30 pub const integerPartOutOfBounds = no_panic.integerPartOutOfBounds;
31 pub const corruptSwitch = no_panic.corruptSwitch;
32 pub const shiftRhsTooBig = no_panic.shiftRhsTooBig;
33 pub const invalidEnumValue = no_panic.invalidEnumValue;
34 pub const forLenMismatch = no_panic.forLenMismatch;
35 pub const copyLenMismatch = no_panic.copyLenMismatch;
36 pub const memcpyAlias = no_panic.memcpyAlias;
37 pub const noreturnReturned = no_panic.noreturnReturned;
38 pub const loadUninstantiableType = no_panic.loadUninstantiableType;
39};
40fn myPanic(msg: []const u8, _: ?usize) noreturn {
41 var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{});
42 stdout_writer.interface.print("new panic message: {s}\n", .{msg}) catch {};
43 std.process.exit(0);
44}
45const std = @import("std");
46const io = std.Io.Threaded.global_single_threaded.io();
test/incremental2/change_panic_handler_explicit/2-main.zig deleted-46
......@@ -1,46 +0,0 @@
1pub fn main() !u8 {
2 var a: u8 = undefined;
3 a = 255;
4 _ = a + 1;
5 return 1;
6}
7const no_panic = std.debug.no_panic;
8pub const panic = struct {
9 pub const call = myPanicNew;
10 pub fn integerOverflow() noreturn {
11 @panic("integer overflow");
12 }
13 pub const sentinelMismatch = no_panic.sentinelMismatch;
14 pub const unwrapError = no_panic.unwrapError;
15 pub const outOfBounds = no_panic.outOfBounds;
16 pub const startGreaterThanEnd = no_panic.startGreaterThanEnd;
17 pub const inactiveUnionField = no_panic.inactiveUnionField;
18 pub const sliceCastLenRemainder = no_panic.sliceCastLenRemainder;
19 pub const reachedUnreachable = no_panic.reachedUnreachable;
20 pub const unwrapNull = no_panic.unwrapNull;
21 pub const castToNull = no_panic.castToNull;
22 pub const incorrectAlignment = no_panic.incorrectAlignment;
23 pub const invalidErrorCode = no_panic.invalidErrorCode;
24 pub const unexpectedErrorCode = no_panic.unexpectedErrorCode;
25 pub const integerOutOfBounds = no_panic.integerOutOfBounds;
26 pub const shlOverflow = no_panic.shlOverflow;
27 pub const shrOverflow = no_panic.shrOverflow;
28 pub const divideByZero = no_panic.divideByZero;
29 pub const exactDivisionRemainder = no_panic.exactDivisionRemainder;
30 pub const integerPartOutOfBounds = no_panic.integerPartOutOfBounds;
31 pub const corruptSwitch = no_panic.corruptSwitch;
32 pub const shiftRhsTooBig = no_panic.shiftRhsTooBig;
33 pub const invalidEnumValue = no_panic.invalidEnumValue;
34 pub const forLenMismatch = no_panic.forLenMismatch;
35 pub const copyLenMismatch = no_panic.copyLenMismatch;
36 pub const memcpyAlias = no_panic.memcpyAlias;
37 pub const noreturnReturned = no_panic.noreturnReturned;
38 pub const loadUninstantiableType = no_panic.loadUninstantiableType;
39};
40fn myPanicNew(msg: []const u8, _: ?usize) noreturn {
41 var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{});
42 stdout_writer.interface.print("third panic message: {s}\n", .{msg}) catch {};
43 std.process.exit(0);
44}
45const std = @import("std");
46const io = std.Io.Threaded.global_single_threaded.io();
test/incremental2/change_panic_handler_explicit/2/main.zig created+46
......@@ -0,0 +1,46 @@
1pub fn main() !u8 {
2 var a: u8 = undefined;
3 a = 255;
4 _ = a + 1;
5 return 1;
6}
7const no_panic = std.debug.no_panic;
8pub const panic = struct {
9 pub const call = myPanicNew;
10 pub fn integerOverflow() noreturn {
11 @panic("integer overflow");
12 }
13 pub const sentinelMismatch = no_panic.sentinelMismatch;
14 pub const unwrapError = no_panic.unwrapError;
15 pub const outOfBounds = no_panic.outOfBounds;
16 pub const startGreaterThanEnd = no_panic.startGreaterThanEnd;
17 pub const inactiveUnionField = no_panic.inactiveUnionField;
18 pub const sliceCastLenRemainder = no_panic.sliceCastLenRemainder;
19 pub const reachedUnreachable = no_panic.reachedUnreachable;
20 pub const unwrapNull = no_panic.unwrapNull;
21 pub const castToNull = no_panic.castToNull;
22 pub const incorrectAlignment = no_panic.incorrectAlignment;
23 pub const invalidErrorCode = no_panic.invalidErrorCode;
24 pub const unexpectedErrorCode = no_panic.unexpectedErrorCode;
25 pub const integerOutOfBounds = no_panic.integerOutOfBounds;
26 pub const shlOverflow = no_panic.shlOverflow;
27 pub const shrOverflow = no_panic.shrOverflow;
28 pub const divideByZero = no_panic.divideByZero;
29 pub const exactDivisionRemainder = no_panic.exactDivisionRemainder;
30 pub const integerPartOutOfBounds = no_panic.integerPartOutOfBounds;
31 pub const corruptSwitch = no_panic.corruptSwitch;
32 pub const shiftRhsTooBig = no_panic.shiftRhsTooBig;
33 pub const invalidEnumValue = no_panic.invalidEnumValue;
34 pub const forLenMismatch = no_panic.forLenMismatch;
35 pub const copyLenMismatch = no_panic.copyLenMismatch;
36 pub const memcpyAlias = no_panic.memcpyAlias;
37 pub const noreturnReturned = no_panic.noreturnReturned;
38 pub const loadUninstantiableType = no_panic.loadUninstantiableType;
39};
40fn myPanicNew(msg: []const u8, _: ?usize) noreturn {
41 var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{});
42 stdout_writer.interface.print("third panic message: {s}\n", .{msg}) catch {};
43 std.process.exit(0);
44}
45const std = @import("std");
46const io = std.Io.Threaded.global_single_threaded.io();
test/incremental2/change_panic_handler_explicit/manifest+3-3
......@@ -2,20 +2,20 @@
22-Mroot=main.zig
33#}
44
5#write main.zig 0-main.zig
5#write main.zig 0/main.zig
66#update
77#check stdout {
88panic message: integer overflow
99#}
1010
11#write main.zig 1-main.zig
11#write main.zig 1/main.zig
1212#update {
1313change the panic handler body#}
1414#check stdout {
1515new panic message: integer overflow
1616#}
1717
18#write main.zig 2-main.zig
18#write main.zig 2/main.zig
1919#update {
2020change the panic handler function value#}
2121#check stdout {
test/src/runner.zig+40-70
......@@ -42,12 +42,13 @@ pub fn main(init: std.process.Init) !void {
4242 const zig_path = zig_path_arg orelse fatal("missing '--zig=path/to/zig'", .{});
4343 const lib_path = lib_path_arg orelse fatal("missing '--lib=path/to/lib'", .{});
4444
45 const test_file = try std.Io.Dir.cwd().openFile(init.io, test_path, .{
45 const cwd: std.Io.Dir = .cwd();
46 const test_file = try cwd.openFile(init.io, test_path, .{
4647 .allow_directory = true,
4748 });
48 const zig_exe = try std.Io.Dir.cwd().openFile(init.io, zig_path, .{});
49 const zig_exe = try cwd.openFile(init.io, zig_path, .{});
4950 defer zig_exe.close(init.io);
50 const lib_dir = try std.Io.Dir.cwd().openDir(init.io, lib_path, .{});
51 const lib_dir = try cwd.openDir(init.io, lib_path, .{});
5152 defer lib_dir.close(init.io);
5253
5354 const src_dir_path = "src_" ++ std.fmt.hex(rand_int: {
......@@ -55,10 +56,10 @@ pub fn main(init: std.process.Init) !void {
5556 init.io.random(@ptrCast(&rand_int));
5657 break :rand_int rand_int;
5758 });
58 var src_dir = try std.Io.Dir.cwd().createDirPathOpen(init.io, src_dir_path, .{});
59 var src_dir = try cwd.createDirPathOpen(init.io, src_dir_path, .{});
5960 defer {
6061 src_dir.close(init.io);
61 if (!keep_src) std.Io.Dir.cwd().deleteTree(init.io, src_dir_path) catch |err| {
62 if (!keep_src) cwd.deleteTree(init.io, src_dir_path) catch |err| {
6263 std.log.warn("fataled to delete tree '{s}': {t}", .{ src_dir_path, err });
6364 };
6465 }
......@@ -423,7 +424,8 @@ fn runTest(
423424 target_string: []const u8,
424425) !void {
425426 const manifest_file = args.manifest_file orelse return error.MissingManifestArg;
426 const src_dir = args.src_dir orelse return error.MissingSrcDir;
427 const src_dir =
428 try (args.src_dir orelse return error.MissingSrcDir).createDirPathOpen(io, target_string, .{});
427429 const target: Compiler.Target = target: {
428430 const backend_split = std.mem.findScalarLast(u8, target_string, '-') orelse
429431 return error.TargetMissingBackend;
......@@ -544,6 +546,8 @@ fn runTest(
544546 },
545547 "-target",
546548 target.triple,
549 "--cache-dir",
550 ".zig-cache",
547551 });
548552 switch (target.mode) {
549553 .whole => {},
......@@ -663,28 +667,6 @@ fn runTest(
663667 };
664668 const body = comp.client.in.take(header.bytes_len) catch unreachable;
665669 switch (header.tag) {
666 .error_bundle => {
667 const error_bundle = try std.zig.Server.allocErrorBundle(arena, body);
668 if (stderr.bufferedLen() > 0) {
669 if (comp.allow_compiler_stderr) {
670 std.log.info("error_bundle stderr:\n{s}", .{stderr.buffered()});
671 } else {
672 fatal("error_bundle unexpected stderr:\n{s}", .{stderr.buffered()});
673 }
674 stderr.tossBuffered();
675 }
676 switch (check) {
677 .errors => if (error_bundle.errorMessageCount() != 0) {
678 @panic("TODO");
679 } else fatal("expected compile errors", .{}),
680 .stdout, .exit, .lldb => if (error_bundle.errorMessageCount() != 0) {
681 try error_bundle.renderToStderr(io, .{}, .auto);
682 fatal("unexpected compile errors", .{});
683 },
684 }
685 comp.state = .idle;
686 break :cmd;
687 },
688670 .emit_digest => {
689671 var r: std.Io.Reader = .fixed(body);
690672 _ = r.takeStruct(std.zig.Server.Message.EmitDigest, .little) catch
......@@ -708,7 +690,7 @@ fn runTest(
708690 }
709691 const digest = r.takeArray(std.Build.Cache.bin_digest_len) catch
710692 unreachable;
711 const result_dir = ".zig-cache" ++ std.Io.Dir.path.sep_str ++
693 const bin_dir = ".zig-cache" ++ std.Io.Dir.path.sep_str ++
712694 "o" ++ std.Io.Dir.path.sep_str ++ std.Build.Cache.binToHex(digest.*);
713695 const bin_name = try std.zig.EmitArtifact.bin.cacheName(arena, .{
714696 .root_name = comp.root_name,
......@@ -719,16 +701,20 @@ fn runTest(
719701 .output_mode = comp.output_mode,
720702 });
721703 const bin_path =
722 try std.Io.Dir.path.join(arena, &.{ result_dir, bin_name });
723 const bin_file = try std.Io.Dir.cwd().openFile(io, bin_path, .{});
704 try std.Io.Dir.path.join(arena, &.{ bin_dir, bin_name });
705 const bin_file = try src_dir.openFile(io, bin_path, .{});
724706 defer bin_file.close(io);
725707 switch (check) {
726708 .errors => unreachable,
727709 .stdout, .exit => {
728 const result = std.process.run(arena, io, .{
710 const result = std.process.run(gpa, io, .{
729711 .exe = .{ .file = bin_file },
730712 .argv = &.{bin_path},
731713 }) catch continue;
714 defer {
715 gpa.free(result.stdout);
716 gpa.free(result.stderr);
717 }
732718 switch (result.term) {
733719 .exited => |code| switch (check) {
734720 .errors, .lldb => unreachable,
......@@ -752,6 +738,28 @@ fn runTest(
752738 .lldb => {},
753739 }
754740 },
741 .error_bundle => {
742 const error_bundle = try std.zig.Server.allocErrorBundle(arena, body);
743 if (stderr.bufferedLen() > 0) {
744 if (comp.allow_compiler_stderr) {
745 std.log.info("error_bundle stderr:\n{s}", .{stderr.buffered()});
746 } else {
747 fatal("error_bundle unexpected stderr:\n{s}", .{stderr.buffered()});
748 }
749 stderr.tossBuffered();
750 }
751 switch (check) {
752 .errors => if (error_bundle.errorMessageCount() != 0) {
753 @panic("TODO");
754 } else fatal("expected compile errors", .{}),
755 .stdout, .exit, .lldb => if (error_bundle.errorMessageCount() != 0) {
756 try error_bundle.renderToStderr(io, .{}, .auto);
757 fatal("unexpected compile errors", .{});
758 },
759 }
760 comp.state = .idle;
761 break :cmd;
762 },
755763 else => {}, // Ignore other messages,
756764 }
757765 }
......@@ -861,44 +869,6 @@ const Compiler = struct {
861869 };
862870 };
863871
864 fn update(comp: *Compiler, io: std.Io) !void {
865 comp.client.serveBodylessMessage(.update) catch |err| switch (err) {
866 error.WriteFailed => return comp.fw.err.?,
867 };
868 while (true) {
869 const header = comp.client.receiveMessageWithMultiReader(
870 &comp.mr,
871 .none,
872 ) catch |err| switch (err) {
873 error.Timeout => unreachable,
874 error.EndOfStream => break,
875 else => |e| return e,
876 };
877 const body = comp.client.in.take(header.bytes_len) catch unreachable;
878 switch (header.tag) {
879 .error_bundle => {
880 return;
881 },
882 .emit_digest => {
883 _ = body;
884 },
885 else => {}, // Ignore other messages,
886 }
887 }
888
889 const buffered_stderr = comp.mr.reader(1).buffered();
890 if (buffered_stderr.len > 0) {
891 if (comp.allow_compiler_stderr) {
892 std.log.info("stderr:\n{s}", .{buffered_stderr});
893 } else {
894 fatal("unexpected stderr:\n{s}", .{buffered_stderr});
895 }
896 }
897
898 try comp.exit(io);
899 fatal("compiler failed to send terminating error_bundle", .{});
900 }
901
902872 fn exit(comp: *Compiler, io: std.Io) !void {
903873 comp.client.serveBodylessMessage(.exit) catch |err| switch (err) {
904874 error.WriteFailed => switch (comp.fw.err.?) {