Repository navigation
π fix(rw): reject a non-bool blocking - #908
gaborbernat merged 2 commits into
Conversation
tox-dev#870 made BaseFileLock and BaseAsyncFileLock reject a blocking that is not a bool, but ReadWriteLock, SoftReadWriteLock and their async wrappers never call _check_blocking. ReadWriteLock then treats the value two ways. Its in-process lock reads it by truthiness, so blocking=0 takes the non-blocking path, while timeout_for_sqlite checks `blocking is False`, so SQLite still busy-waits the full timeout. On a contended lock, acquire_write(timeout=2, blocking=0) took 2.1 s to raise Timeout where blocking=False fails at once, and the default timeout of -1 waits on SQLite's cap. A truthy "false" becomes a blocking wait on every read-write lock. Check blocking in _resolve_read_write_timeout, which every sync and async read-write acquire passes through, and in both constructors, the way FileLockMeta validates it before building the instance.
Ekko82
left a comment
There was a problem hiding this comment.
With a real held SQLite write lock on Windows (CPython 3.13.9, SQLite 3.51.0), both AsyncReadWriteLock.acquire_read(timeout=0.12, blocking=0) and acquire_write(...) remained blocked on base 2ac1e92 until their subprocesses were stopped at a 3-second deadline. At bbfa585, both raise TypeError. The base async owner table drops the deadline for falsy 0, then SQLite handles it differently from False.
The head passed all 89 targeted public-API checks. The base had 38 rejection failures and 49 passing controls, plus the two separately terminated cases. Coverage includes native Windows FileLock/AsyncFileLock controls and synchronous/asynchronous SQLite and soft read/write locks, numeric durations, valid True/False, acquire(blocking=None) inheritance, release/reacquire, and reader/writer exclusion. All 49 controls passed on both refs.
Both Git-source fixtures used the same generated version.py metadata stand-in (version = '0+source-validation'). The full upstream suite and tox matrix were not run.
List the non-bool blocking TypeError in every read-write acquire and context-manager docstring, and correct comments that misstated the change: a bad default is caught at acquire anyway, so the metaclass check only moves the error to construction, and the contended test's contender has no 30 s timeout.
#870 made
FileLockraiseTypeErrorfor ablockingthat is not abool, butReadWriteLock,SoftReadWriteLockand their async wrappers still took any value. π OnReadWriteLockthat split one acquire in two: the in-process lock readblocking=0as non-blocking while SQLite still got the full busy timeout, so a probe that should fail at once waited up to the timeout (with the default-1, SQLite's cap of about 23 days). A truthy value such as"false"turned every read-write lock type's single attempt into a blocking wait.All four read-write lock types now reject a non-bool
blockingwith the sameTypeErrorasFileLock. The constructors check the instance default, and the shared timeout resolution that every acquire passes through checks the per-call value. That covers reentrant holds, the async per-task table and ablockingattribute changed after construction. A rejected call takes no lock and leaves an existing hold's level unchanged.Callers passing
0,1or another non-boolblockingto a read-write lock now get aTypeErrorwhere they used to get a lock, a timeout or a long wait. The acquire and context-manager docstrings list the new error.