summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/selfmount.py36
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