Skip to content

🐛 fix(unix): auto-fallback to SoftFileLock on ENOSYS#480

Merged
gaborbernat merged 1 commit intotox-dev:mainfrom
gaborbernat:fix-soft-stale-windows
Feb 14, 2026
Merged

🐛 fix(unix): auto-fallback to SoftFileLock on ENOSYS#480
gaborbernat merged 1 commit intotox-dev:mainfrom
gaborbernat:fix-soft-stale-windows

Conversation

@gaborbernat
Copy link
Member

@gaborbernat gaborbernat commented Feb 14, 2026

On platforms like Android/Termux and network filesystems (NFS, CIFS), fcntl imports fine but flock() fails at runtime with ENOSYS. 💥 Previously this raised NotImplementedError, leaving users no recourse except monkey-patching filelock.FileLock = filelock.SoftFileLock before any other import — fragile and easy to get wrong.

This catches ENOSYS in UnixFileLock._acquire(), cleans up the leftover lock file, and transparently swaps self.__class__ to SoftFileLock (or AsyncSoftFileLock for async instances). Both classes share the same BaseFileLock layout with no extra instance state, so the swap is safe and preserves all context. ✨ Subsequent acquire/release cycles go straight through the soft path with no repeated flock() attempts.

The soft fallback relies on O_CREAT | O_EXCL which is atomic on NFSv3+ with Linux kernel 2.6+ and endorsed by CERT as secure against TOCTOU. Symlink attacks are mitigated by O_NOFOLLOW already used in SoftFileLock._acquire(). On Android/Termux the local filesystem (ext4/f2fs) provides full O_EXCL guarantees. The __class__ swap is validated by CPython's compatible_for_assignment() when both types share the same base layout.

Fixes #289, fixes #349

@gaborbernat gaborbernat force-pushed the fix-soft-stale-windows branch from 7ce7ea1 to eedcc63 Compare February 14, 2026 03:14
@gaborbernat gaborbernat marked this pull request as draft February 14, 2026 03:14
@gaborbernat gaborbernat changed the title 🐛 fix(soft,unix): harden stale detection and auto-fallback on ENOSYS 🐛 fix(unix): auto-fallback to SoftFileLock on ENOSYS Feb 14, 2026
On platforms like Android/Termux and network filesystems (NFS, CIFS),
fcntl imports fine but flock() fails at runtime with ENOSYS. Previously
this raised NotImplementedError, leaving users no recourse except
monkey-patching filelock.FileLock before any other imports.

Now UnixFileLock catches ENOSYS, cleans up the leftover lock file, and
swaps __class__ to SoftFileLock (or AsyncSoftFileLock for async
instances). Both classes share the same BaseFileLock layout with no
extra instance state, so the swap is safe and preserves all context.
Subsequent acquire/release calls go straight through the soft path.

Fixes tox-dev#289, fixes tox-dev#349
@gaborbernat gaborbernat force-pushed the fix-soft-stale-windows branch from eedcc63 to 4ce9231 Compare February 14, 2026 03:17
@gaborbernat gaborbernat marked this pull request as ready for review February 14, 2026 03:29
@gaborbernat gaborbernat merged commit 7dfdb02 into tox-dev:main Feb 14, 2026
32 checks passed
@gaborbernat gaborbernat deleted the fix-soft-stale-windows branch February 14, 2026 04:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Android/Termux doesn't have flock, use lockf, SoftFileLock, or no lock? Allow disabling fcntl (and use softfilelock) with environment variable

1 participant