From cd963ba38d77622b2971e7ea0bdc916ec5685630 Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Wed, 7 Jan 2026 00:29:36 +0000 Subject: [PATCH] Io.Threaded: fix bad assertion Resolves: https://codeberg.org/ziglang/zig/issues/30717 --- lib/std/Io/Threaded.zig | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/lib/std/Io/Threaded.zig b/lib/std/Io/Threaded.zig index ed40914950..eb9b048cbd 100644 --- a/lib/std/Io/Threaded.zig +++ b/lib/std/Io/Threaded.zig @@ -2109,25 +2109,28 @@ fn await( .tag = .pending_canceled, .thread = .null, }, .acq_rel); // acquire results if complete; release `future.awaiter` - switch (pre_cancel_status.tag) { + const done_status = switch (pre_cancel_status.tag) { .pending => unreachable, // invalid state: we already awaited - .pending_awaited => { + .pending_awaited => done_status: { const working_thread = pre_cancel_status.thread.unpack(); future.waitForCancelWithSignaling(t, &num_completed, @alignCast(working_thread)); + break :done_status future.status.load(.monotonic); }, .pending_canceled => unreachable, // `await` raced with `cancel` - .done => { + .done => done_status: { // The task just finished, but we still need to wait for the signal, because the // task thread already figured out that they need to update `future.awaiter`. future.waitForCancelWithSignaling(t, &num_completed, null); + // Also, we have clobbered `future.status.tag` to `.pending_canceled`, but that's + // not actually a problem for the logic below. + break :done_status pre_cancel_status; }, - } + }; // If the future did not acknowledge the cancelation, we need to mark it outstanding - // for us. Because `future.status.tag == .done`, the information about whether there - // was an acknowledged cancelation is encoded in `future.status.thread`. - const final_status = future.status.load(.monotonic); - assert(final_status.tag == .done); - switch (final_status.thread) { + // for us. Because `done_status.tag == .done`, the information about whether there + // was an acknowledged cancelation is encoded in `done_status.thread`. + assert(done_status.tag == .done); + switch (done_status.thread) { .null => recancelInner(), // cancelation was not acknowledged, so it's ours .all_ones => {}, // cancelation was acknowledged, so it was this task's job to propagate it _ => unreachable,