diff options
| author | Gabriel Schneider <[email protected]> | 2026-09-28 10:46:11 -0300 |
|---|---|---|
| committer | Gabriel Schneider <[email protected]> | 2026-10-01 00:12:14 -0300 |
| commit | 73e797e3f31eb52b0074b86cd16949c827b75670 (patch) | |
| tree | a2be3b24014daccf9140b9fc10907d8a42c73f4c /test | |
| parent | b03338789f5c9f3619a1ace7fcda842bc073c4dc (diff) | |
| download | pardes-73e797e3f31eb52b0074b86cd16949c827b75670.tar.gz pardes-73e797e3f31eb52b0074b86cd16949c827b75670.zip | |
A lock another open holds fails at once with file in use instead of parking
A contended lock parked until the holder unlocked, but through a kernel
or FUSE mount the kernel serialises writes to one file, so the parked
lock held up the holder's own unlock and close on that ctl, and the two
deadlocked. acme's qlock blocks; here the second lock is refused at once
with file in use (EBUSY) and the client retries, and nothing parks on
the lock any more.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Diffstat (limited to 'test')
| -rw-r--r-- | test/fs.py | 18 |
1 files changed, 9 insertions, 9 deletions
@@ -218,21 +218,21 @@ def discovery(binary, embedded=False): client.write('/exec', b'Msg woken\n') reader.join(5) assert woke and woke[0].endswith(b' woken\n'), woke - # A pane's ctl takes acme's lock: a second open's lock waits until - # the holder unlocks, and nothing else waits on it meanwhile. + # A pane's ctl takes acme's lock: a second open's lock fails at + # once with "file in use" until the holder unlocks, and nothing + # else waits on it meanwhile. with Client(address) as other: mine = client.open(f'/pane/{first}/ctl', 2) client.rpc(118, struct.pack('<IQI', mine, 0, 5) + b'lock\n') theirs = other.open(f'/pane/{first}/ctl', 1) - locked = [] - locker = threading.Thread(target=lambda: locked.append(other.rpc(118, struct.pack('<IQI', theirs, 0, 5) + b'lock\n')), daemon=True) - locker.start() - time.sleep(.2) - assert not locked + try: + other.rpc(118, struct.pack('<IQI', theirs, 0, 5) + b'lock\n') + raise AssertionError('a second lock was taken') + except OSError as refused: + assert 'file in use' in str(refused), refused client.write(f'/pane/{first}/addr', b'#0') client.rpc(118, struct.pack('<IQI', mine, 0, 7) + b'unlock\n') - locker.join(5) - assert locked, 'a lock waiting on another open goes once it unlocks' + other.rpc(118, struct.pack('<IQI', theirs, 0, 5) + b'lock\n') client.close(mine) other.close(theirs) # /focus names the pane with the keyboard and moves it, as rio's |
