Skip to content

πŸ› fix(rw): reject a non-bool blocking - #908

Merged
gaborbernat merged 2 commits into
tox-dev:mainfrom
abhishekcpp007:fix/rw-lock-reject-non-bool-blocking
Nov 4, 2026
Merged

gaborbernat merged 2 commits into
tox-dev:mainfrom
abhishekcpp007:fix/rw-lock-reject-non-bool-blocking

Conversation

@abhishekcpp007

@abhishekcpp007 abhishekcpp007 commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

#870 made FileLock raise TypeError for a blocking that is not a bool, but ReadWriteLock, SoftReadWriteLock and their async wrappers still took any value. πŸ› On ReadWriteLock that split one acquire in two: the in-process lock read blocking=0 as 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 blocking with the same TypeError as FileLock. 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 a blocking attribute changed after construction. A rejected call takes no lock and leaves an existing hold's level unchanged.

Callers passing 0, 1 or another non-bool blocking to a read-write lock now get a TypeError where they used to get a lock, a timeout or a long wait. The acquire and context-manager docstrings list the new error.

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 Ekko82 left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.
@gaborbernat gaborbernat changed the title πŸ› fix(rw): reject a non-bool blocking in read-write locks πŸ› fix(rw): reject a non-bool blocking Nov 4, 2026
@gaborbernat gaborbernat added the bug label Nov 4, 2026
@gaborbernat
gaborbernat merged commit 030c5e2 into tox-dev:main Nov 4, 2026
53 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants