From c199124a84f3c4b8d1eabb10620ae5be7d0275f9 Mon Sep 17 00:00:00 2001 From: Loris Cro Date: Fri, 7 Nov 2025 13:33:45 +0100 Subject: [PATCH] fix logic bug in groupAsync --- lib/std/Io/Threaded.zig | 56 ++++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/lib/std/Io/Threaded.zig b/lib/std/Io/Threaded.zig index 4f4b547743707b78ec63cfd46fd33698988afb20..24ce92dfb1962253b90d3d5e64356a9488019e80 100644 --- a/lib/std/Io/Threaded.zig +++ b/lib/std/Io/Threaded.zig @@ -695,38 +695,38 @@ fn groupAsync( t.mutex.lock(); + if (t.available_thread_count == 0) { + if (t.cpu_count != 0 and t.threads.items.len >= t.cpu_count) { + t.mutex.unlock(); + gc.free(gpa); + return start(group, context.ptr); + } + + t.threads.ensureUnusedCapacity(gpa, 1) catch { + t.mutex.unlock(); + gc.free(gpa); + return start(group, context.ptr); + }; + + const thread = std.Thread.spawn( + .{ .stack_size = t.stack_size }, + worker, + .{t}, + ) catch { + t.mutex.unlock(); + gc.free(gpa); + return start(group, context.ptr); + }; + + t.threads.appendAssumeCapacity(thread); + } else { + t.available_thread_count -= 1; + } + // Append to the group linked list inside the mutex to make `Io.Group.async` thread-safe. gc.node = .{ .next = @ptrCast(@alignCast(group.token)) }; group.token = &gc.node; - if (t.available_thread_count == 0) { - if (t.cpu_count != 0 and t.threads.items.len >= t.cpu_count) { - t.mutex.unlock(); - gc.free(gpa); - return start(group, context.ptr); - } - - t.threads.ensureUnusedCapacity(gpa, 1) catch { - t.mutex.unlock(); - gc.free(gpa); - return start(group, context.ptr); - }; - - const thread = std.Thread.spawn( - .{ .stack_size = t.stack_size }, - worker, - .{t}, - ) catch { - t.mutex.unlock(); - gc.free(gpa); - return start(group, context.ptr); - }; - - t.threads.appendAssumeCapacity(thread); - } else { - t.available_thread_count -= 1; - } - t.run_queue.prepend(&gc.closure.node); // This needs to be done before unlocking the mutex to avoid a race with -- 2.54.0