authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-01-07 00:29:36+00:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-01-07 11:27:21+01:00
logcd963ba38d77622b2971e7ea0bdc916ec5685630
tree51e53bc8affaf52ac024cc65bd0891fe340e30cf
parent28b83e3b0274a52b1d02a4117edd9fc6636917de

Io.Threaded: fix bad assertion

Resolves: https://codeberg.org/ziglang/zig/issues/30717

1 files changed, 12 insertions(+), 9 deletions(-)

lib/std/Io/Threaded.zig+12-9
......@@ -2109,25 +2109,28 @@ fn await(
21092109 .tag = .pending_canceled,
21102110 .thread = .null,
21112111 }, .acq_rel); // acquire results if complete; release `future.awaiter`
2112 switch (pre_cancel_status.tag) {
2112 const done_status = switch (pre_cancel_status.tag) {
21132113 .pending => unreachable, // invalid state: we already awaited
2114 .pending_awaited => {
2114 .pending_awaited => done_status: {
21152115 const working_thread = pre_cancel_status.thread.unpack();
21162116 future.waitForCancelWithSignaling(t, &num_completed, @alignCast(working_thread));
2117 break :done_status future.status.load(.monotonic);
21172118 },
21182119 .pending_canceled => unreachable, // `await` raced with `cancel`
2119 .done => {
2120 .done => done_status: {
21202121 // The task just finished, but we still need to wait for the signal, because the
21212122 // task thread already figured out that they need to update `future.awaiter`.
21222123 future.waitForCancelWithSignaling(t, &num_completed, null);
2124 // Also, we have clobbered `future.status.tag` to `.pending_canceled`, but that's
2125 // not actually a problem for the logic below.
2126 break :done_status pre_cancel_status;
21232127 },
2124 }
2128 };
21252129 // If the future did not acknowledge the cancelation, we need to mark it outstanding
2126 // for us. Because `future.status.tag == .done`, the information about whether there
2127 // was an acknowledged cancelation is encoded in `future.status.thread`.
2128 const final_status = future.status.load(.monotonic);
2129 assert(final_status.tag == .done);
2130 switch (final_status.thread) {
2130 // for us. Because `done_status.tag == .done`, the information about whether there
2131 // was an acknowledged cancelation is encoded in `done_status.thread`.
2132 assert(done_status.tag == .done);
2133 switch (done_status.thread) {
21312134 .null => recancelInner(), // cancelation was not acknowledged, so it's ours
21322135 .all_ones => {}, // cancelation was acknowledged, so it was this task's job to propagate it
21332136 _ => unreachable,