Files
RustPython/extra_tests/snippets/stdlib_multiprocessing_condition.py
T
Jeong, YunWon 7f610e593f Fix ctypes from_buffer writes and unskip passing MP tests (#8744)
* Fix ctypes from_buffer writes and unskip passing MP tests

Write char-array .value/.raw through borrowed buffers instead of
Cow::to_mut(), which copied shared memory into a private buffer.

Unskip connection pickling, sharedctypes, Condition notify, and
concurrent.futures interpreter-shutdown tests. Cover forkserver
Condition notify and shared ctypes char arrays in extra_tests.

Assisted-by: Grok:4.6

* Unskip linux RLock repr; keep fork pickling hang skip

test_repr_rlock passed on Linux spawn/fork/forkserver. Connection
pickling hangs under the fork start method, so skip it only there.

Build the apple-container image from rust:bookworm; rust:bullseye
apt indexes 404.

Assisted-by: Grok:4.6
2026-09-20 06:43:30 +09:00

92 lines
2.3 KiB
Python

"""Thread+process Condition notify must wake every waiter."""
import multiprocessing
import threading
def wait_on_condition(cond, started, woken):
cond.acquire()
started.release()
cond.wait()
woken.release()
cond.release()
def join_workers(workers):
for worker in workers:
worker.join(timeout=5)
assert not worker.is_alive()
def wait_sem(sem, msg):
assert sem.acquire(timeout=5), msg
def notify_all_six(ctx):
cond = ctx.Condition()
started = ctx.Semaphore(0)
woken = ctx.Semaphore(0)
workers = []
for _ in range(3):
proc = ctx.Process(target=wait_on_condition, args=(cond, started, woken))
proc.daemon = True
proc.start()
workers.append(proc)
thread = threading.Thread(target=wait_on_condition, args=(cond, started, woken))
thread.daemon = True
thread.start()
workers.append(thread)
for i in range(6):
wait_sem(started, f"waiter {i} did not enter Condition.wait()")
cond.acquire()
cond.notify_all()
cond.release()
for i in range(6):
wait_sem(woken, f"waiter {i} did not wake")
join_workers(workers)
def notify_one_then_the_other(ctx):
cond = ctx.Condition()
started = ctx.Semaphore(0)
woken = ctx.Semaphore(0)
proc = ctx.Process(target=wait_on_condition, args=(cond, started, woken))
proc.daemon = True
proc.start()
thread = threading.Thread(target=wait_on_condition, args=(cond, started, woken))
thread.daemon = True
thread.start()
wait_sem(started, "process did not enter Condition.wait()")
wait_sem(started, "thread did not enter Condition.wait()")
cond.acquire()
cond.notify()
cond.release()
wait_sem(woken, "first waiter did not wake")
cond.acquire()
cond.notify()
cond.release()
wait_sem(woken, "second waiter did not wake")
join_workers([proc, thread])
if __name__ == "__main__":
multiprocessing.freeze_support()
methods = ["spawn"]
if "forkserver" in multiprocessing.get_all_start_methods():
methods.append("forkserver")
# Enough repeats to surface a lost-wakeup race in CI snippets.
for method in methods:
ctx = multiprocessing.get_context(method)
for _ in range(20):
notify_all_six(ctx)
notify_one_then_the_other(ctx)