authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-04-26 13:11:35-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-04-27 08:24:32-07:00
log8c52c6ec6c4d6648ae4e2f11dd620d95599f4039
treec97b4764565825488e89d7d52af383194c58c6d1
parent131b328c10abde0193c13073b5ab82f0031fb121

std: prevent the possibility of deadlocks in some threaded tests


1 files changed, 20 insertions(+), 3 deletions(-)

lib/std/Thread/Condition.zig+20-3
......@@ -330,10 +330,12 @@ test "Condition - wait and signal" {
330330 mutex: Mutex = .{},
331331 cond: Condition = .{},
332332 threads: [num_threads]std.Thread = undefined,
333 spawn_count: std.math.IntFittingRange(0, num_threads) = 0,
333334
334335 fn run(self: *@This()) void {
335336 self.mutex.lock();
336337 defer self.mutex.unlock();
338 self.spawn_count += 1;
337339
338340 self.cond.wait(&self.mutex);
339341 self.cond.timedWait(&self.mutex, std.time.ns_per_ms) catch {};
......@@ -346,7 +348,14 @@ test "Condition - wait and signal" {
346348 t.* = try std.Thread.spawn(.{}, MultiWait.run, .{&multi_wait});
347349 }
348350
349 std.time.sleep(100 * std.time.ns_per_ms);
351 while (true) {
352 std.time.sleep(100 * std.time.ns_per_ms);
353
354 multi_wait.mutex.lock();
355 defer multi_wait.mutex.unlock();
356 // Make sure all of the threads have finished spawning to avoid a deadlock.
357 if (multi_wait.spawn_count == num_threads) break;
358 }
350359
351360 multi_wait.cond.signal();
352361 for (multi_wait.threads) |t| {
......@@ -367,10 +376,12 @@ test "Condition - signal" {
367376 cond: Condition = .{},
368377 notified: bool = false,
369378 threads: [num_threads]std.Thread = undefined,
379 spawn_count: std.math.IntFittingRange(0, num_threads) = 0,
370380
371381 fn run(self: *@This()) void {
372382 self.mutex.lock();
373383 defer self.mutex.unlock();
384 self.spawn_count += 1;
374385
375386 // Use timedWait() a few times before using wait()
376387 // to test multiple threads timing out frequently.
......@@ -394,10 +405,16 @@ test "Condition - signal" {
394405 t.* = try std.Thread.spawn(.{}, SignalTest.run, .{&signal_test});
395406 }
396407
397 {
398 // Wait for a bit in hopes that the spawned threads start queuing up on the condvar
408 while (true) {
399409 std.time.sleep(10 * std.time.ns_per_ms);
400410
411 signal_test.mutex.lock();
412 defer signal_test.mutex.unlock();
413 // Make sure at least one thread has finished spawning to avoid testing nothing.
414 if (signal_test.spawn_count > 0) break;
415 }
416
417 {
401418 // Wake up one of them (outside the lock) after setting notified=true.
402419 defer signal_test.cond.signal();
403420