diff options
Diffstat (limited to 'test')
| -rw-r--r-- | test/selfmount.py | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/test/selfmount.py b/test/selfmount.py index c6565b5e..5aa9749a 100644 --- a/test/selfmount.py +++ b/test/selfmount.py @@ -267,6 +267,42 @@ def run(binary): took = time.monotonic() - started check(got == '0' and took < 5 and 'filter-hi' in client.read('/log').decode(), f'an Edit filter writing its own ctl through the mount answers promptly ({got!r}, {took:.1f}s)') + # Another session dies under a burst of reads of it through the + # registry mount: every read returns (an error is fine), none + # hangs. 9ns invalidates the dead entry from a thread of its own, + # never the one that must answer the reads holding its parent. + other = name + 'k' + other_sock = f'{runtime}/pardes-9p-{other}.sock' + other_env = dict(env, PARDES_DUMP=f'/tmp/{other}.dump.zon') + other_pid, other_master = pty.fork() + if other_pid == 0: + os.execve(binary, [binary, '--tty', '--9p=' + other], other_env) + os.set_blocking(other_master, False) + deadline = time.monotonic() + 15 + while not os.path.exists(other_sock) and time.monotonic() < deadline: + try: + os.read(other_master, 65536) + except OSError: + pass + time.sleep(.05) + codes = Path(f'/tmp/{name}.codes') + codes.unlink(missing_ok=True) + + def kill_other(): + time.sleep(1.5) + os.kill(other_pid, signal.SIGKILL) + killer = threading.Thread(target=kill_other, daemon=True) + killer.start() + ran = run((f"for k in 1 2 3 4 5; do (end=$((SECONDS+4)); while [ $SECONDS -lt $end ]; do " + f"timeout 10 cat /mnt/9p/pardes/{other}/index > /dev/null 2>&1; echo $? >> {codes}; done) & done; wait\n").encode()) + killer.join(5) + os.waitpid(other_pid, 0) + got_codes = codes.read_text().split() if codes.exists() else [] + codes.unlink(missing_ok=True) + for path in (other_sock, f'/tmp/{other}.dump.zon'): + Path(path).unlink(missing_ok=True) + check(ran == '0' and got_codes and '124' not in got_codes, + f'reads of a session killed under them all return ({ran!r}, {len(got_codes)} reads, {got_codes.count("124")} hung)') # Forty event reads held through the mount, a follower each, and # the mount still answers the rest: 9ns keeps workers past what # the editor holds (128), so `cat layout` is not queued behind |
