Commit 8c52c6ec6c

Jacob Young <jacobly0@users.noreply.github.com>
2023-04-26 19:11:35
std: prevent the possibility of deadlocks in some threaded tests
1 parent 131b328
Changed files (1)
lib
std
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();