diff options
| author | Gabriel Schneider <[email protected]> | 2026-09-29 11:26:42 -0300 |
|---|---|---|
| committer | Gabriel Schneider <[email protected]> | 2026-10-01 00:12:16 -0300 |
| commit | 0e6501ce210481c095e6f70a27e7f125f7af3761 (patch) | |
| tree | 0abf4b55e8eb4f836a3ad10963cbefd94efb8599 /test | |
| parent | 1ac8fbeedaf7cba881a7423b92ead1f739b8ac21 (diff) | |
| download | pardes-0e6501ce210481c095e6f70a27e7f125f7af3761.tar.gz pardes-0e6501ce210481c095e6f70a27e7f125f7af3761.zip | |
A pty/ctl exec that cannot start its shell keeps the one running
Each host closed the running shell before it forked the new one, so an exec whose shell failed left the pane with none and later runs answered error shell gone. A shell not there is now refused up front, and every host starts the new shell first, replacing the old only once the close-on-exec pipe says it ran; a failure there is only said (restartFailed).
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Diffstat (limited to 'test')
| -rw-r--r-- | test/fs.py | 40 |
1 files changed, 28 insertions, 12 deletions
@@ -442,6 +442,27 @@ def run_file(binary): assert run(client, term, b'true\n') == b'exit 0\n' assert client.read(f'/pane/{term}/pty/ctl').split()[2] == b'2', client.read(f'/pane/{term}/pty/ctl') client.write(f'/pane/{term}/pty/ctl', b'winsize 80 24\n') + # A shell started again that cannot start (its directory is + # there but cannot be entered) fails the write and leaves the + # running shell be: runs still work. + locked = root / 'locked' + locked.mkdir() + assert run(client, term, f'cd {locked}\n'.encode()) == b'exit 0\n' + deadline = time.monotonic() + 5 + while str(locked).encode() not in client.read('/index'): + assert time.monotonic() < deadline, client.read('/index') + time.sleep(.05) + locked.chmod(0o600) + try: + client.write(f'/pane/{term}/pty/ctl', b'exec\n') + raise AssertionError('pty/ctl exec of a shell that cannot start was taken') + except OSError as refused: + assert 'shell' in str(refused), refused + finally: + locked.chmod(0o755) + kept = run(client, term, b'true\n') + assert kept == b'exit 0\n', (kept, client.read('/log')[-600:]) + assert run(client, term, f'cd {root}\n'.encode()) == b'exit 0\n' with Client(address) as other: slow = [] waiter = threading.Thread(target=lambda: slow.append(run(other, term, b'sleep 1\n')), daemon=True) @@ -522,20 +543,15 @@ def new_terminals_named_once(binary): bad.write_bytes(b'#!/nonexistent/interp\n') bad.chmod(0o755) panes = client.read('/index') - try: - client.write('/pane/1/ctl', f'Tty {bad}\n'.encode()) - raise AssertionError('Tty of a shell that cannot start was taken') - except OSError as refused: - assert 'shell' in str(refused), refused + for where, line in (('/pane/1/ctl', f'Tty {bad}\n'), ('/ctl', f'Shell {bad}\n')): + try: + client.write(where, line.encode()) + raise AssertionError(f'{line} of a shell that cannot start was taken') + except OSError as refused: + assert 'interpreter /nonexistent/interp not found' in str(refused), refused time.sleep(.3) assert client.read('/index').count(b'\n') == panes.count(b'\n'), client.read('/index') - client.write('/ctl', f'Shell {bad}\n'.encode()) - try: - client.write(f'/pane/{made[0]}/pty/ctl', b'exec\n') - raise AssertionError('pty/ctl exec of a shell that cannot start was taken') - except OSError as refused: - assert 'shell' in str(refused), refused - client.write('/ctl', b'Shell\n') + assert b'shell: shell not found' not in client.read('/log'), client.read('/log') assert str(made[0]).encode() in b' '.join(r.split()[0] for r in client.read('/index').splitlines()) |
