summaryrefslogtreecommitdiff
path: root/test/fs.py
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-09-28 10:46:11 -0300
committerGabriel Schneider <[email protected]>2026-10-01 00:12:14 -0300
commit73e797e3f31eb52b0074b86cd16949c827b75670 (patch)
treea2be3b24014daccf9140b9fc10907d8a42c73f4c /test/fs.py
parentb03338789f5c9f3619a1ace7fcda842bc073c4dc (diff)
downloadpardes-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/fs.py')
-rw-r--r--test/fs.py18
1 files changed, 9 insertions, 9 deletions
diff --git a/test/fs.py b/test/fs.py
index a6d24e0b..816f416c 100644
--- a/test/fs.py
+++ b/test/fs.py
@@ -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