zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit 8c52c6ec6c4d6648ae4e2f11dd620d95599f4039 (tree)
parent 131b328c10abde0193c13073b5ab82f0031fb121
Author: Jacob Young <jacobly0@users.noreply.github.com>
Date:   Wed, 26 Apr 2023 13:11:35 -0400

std: prevent the possibility of deadlocks in some threaded tests

Diffstat:
Mlib/std/Thread/Condition.zig | 23++++++++++++++++++++---
1 file changed, 20 insertions(+), 3 deletions(-)

diff --git a/lib/std/Thread/Condition.zig b/lib/std/Thread/Condition.zig @@ -330,10 +330,12 @@ test "Condition - wait and signal" { mutex: Mutex = .{}, cond: Condition = .{}, threads: [num_threads]std.Thread = undefined, + spawn_count: std.math.IntFittingRange(0, num_threads) = 0, fn run(self: *@This()) void { self.mutex.lock(); defer self.mutex.unlock(); + self.spawn_count += 1; self.cond.wait(&self.mutex); self.cond.timedWait(&self.mutex, std.time.ns_per_ms) catch {}; @@ -346,7 +348,14 @@ test "Condition - wait and signal" { t.* = try std.Thread.spawn(.{}, MultiWait.run, .{&multi_wait}); } - std.time.sleep(100 * std.time.ns_per_ms); + while (true) { + std.time.sleep(100 * std.time.ns_per_ms); + + multi_wait.mutex.lock(); + defer multi_wait.mutex.unlock(); + // Make sure all of the threads have finished spawning to avoid a deadlock. + if (multi_wait.spawn_count == num_threads) break; + } multi_wait.cond.signal(); for (multi_wait.threads) |t| { @@ -367,10 +376,12 @@ test "Condition - signal" { cond: Condition = .{}, notified: bool = false, threads: [num_threads]std.Thread = undefined, + spawn_count: std.math.IntFittingRange(0, num_threads) = 0, fn run(self: *@This()) void { self.mutex.lock(); defer self.mutex.unlock(); + self.spawn_count += 1; // Use timedWait() a few times before using wait() // to test multiple threads timing out frequently. @@ -394,10 +405,16 @@ test "Condition - signal" { t.* = try std.Thread.spawn(.{}, SignalTest.run, .{&signal_test}); } - { - // Wait for a bit in hopes that the spawned threads start queuing up on the condvar + while (true) { std.time.sleep(10 * std.time.ns_per_ms); + signal_test.mutex.lock(); + defer signal_test.mutex.unlock(); + // Make sure at least one thread has finished spawning to avoid testing nothing. + if (signal_test.spawn_count > 0) break; + } + + { // Wake up one of them (outside the lock) after setting notified=true. defer signal_test.cond.signal();