From 406f483288c7689bdd2e1f3f68b276c61ca9412a Mon Sep 17 00:00:00 2001 From: Gabriel Schneider Date: Thu, 1 Oct 2026 20:50:48 -0300 Subject: An Edit's held write: < | > commands no longer block their 9P connection (answered like a held read, so a status read or a filter reading the session's own mount runs beside it), a Tflush or hang-up of the write kills the commands' process groups and changes nothing; e loads by Get's way (asked once, clean after, undo puts the name back); ~ in e r w f B; B checks every name first; an Edit that runs commands is a write of its own, refused up front with other lines; Edit's +Errors output keeps the keyboard where it was; X goes in pane order; a refused write open says its errno; the reference's Coming from acme rows say what Get file's undo, failure and directory refusal, Putall's answer, Zerox across Dump and Incl's directories now do Co-Authored-By: Claude Opus 5.5 --- test/fs.py | 31 +++++++++++++++++++++++++++++++ test/selfmount.py | 26 ++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) (limited to 'test') diff --git a/test/fs.py b/test/fs.py index 59668c57..b593981c 100644 --- a/test/fs.py +++ b/test/fs.py @@ -1085,6 +1085,37 @@ def edit_commands(binary): assert time.monotonic() - began < .5 and not done.is_set(), 'the editor waited on the command' worker.join(timeout=15) assert done.is_set() + # On the same connection: the Edit's write is held, and a read sent + # after it is answered first; a Tflush of it stops it, changes + # nothing, and frees the way for the next Edit. + def send(kind, tag, payload): + client.socket.sendall(struct.pack(' {mount}/pane/{edited}/ctl & sleep .5; " + f"s=$(date +%s%N); timeout 5 cat {mount}/status > /dev/null; e=$(date +%s%N); " + f"echo $(( (e - s) / 1000000 )) > {took}; wait\n").encode()) + ms = int(took.read_text()) if took.exists() else -1 + took.unlink(missing_ok=True) + check(ran == '0' and 0 <= ms < 1000, f'a status read beside a slow Edit answers at once ({ms} ms)') + check(client.read(f'/pane/{edited}/body') == b'apple\npear\n', 'and the slow Edit applied') + ran = run(f"echo 'Edit $ < cat {mount}/pane/{edited}/body' > {mount}/pane/{edited}/ctl\n".encode()) + check(ran == '0' and client.read(f'/pane/{edited}/body') == b'apple\npear\napple\npear\n', + f'an Edit whose command reads the session through its mount ({ran!r})') + # An interrupted Edit write is flushed: its command is stopped and + # nothing changes, and the next Edit runs. + flushed = Path(f'/tmp/{name}.flushed') + ran = run((f"timeout -s INT 1 sh -c \"echo 'Edit , | sleep 4; tr a-z A-Z' > {mount}/pane/{edited}/ctl\"; " + f"echo $? > {flushed}; sleep 1; echo 'Edit 1 | tr p P' > {mount}/pane/{edited}/ctl; echo $? >> {flushed}\n").encode()) + codes = flushed.read_text().split() if flushed.exists() else [] + flushed.unlink(missing_ok=True) + time.sleep(4.5) + check(codes == ['124', '0'] and client.read(f'/pane/{edited}/body') == b'aPPle\npear\napple\npear\n', + f'an interrupted Edit changes nothing, and the next runs ({codes!r}, {client.read(f"/pane/{edited}/body")!r})') client.write('/exec', b'Msg still here\n') text = ''.join(cell[0] for cell in client.screen()['cells']) check('still here' in text, 'the editor answers after all of that') -- cgit v1.3