Severity: Enhancement (callers that provision a stable lock identity cannot disable best-effort pathname deletion)
Summary
I would like WindowsFileLock to expose a backward-compatible option that
preserves the lock-file pathname after release. Version 3.29.7 intentionally
attempts to delete it after closing the descriptor. That behavior is convenient
for cleanup, but some local-filesystem protocols require the same path and file
identity to remain available across acquisitions for ACLs, auditing, or
holder-diagnostic continuity.
Environment
- package/version:
filelock 3.29.7
- source: commit
1efb8932c08789deb08ad93a91d8996cc36bb9cc
- platform: Windows local filesystems
- affected API:
WindowsFileLock
Reproduction
-
Run the attached filelock_windows_delete_on_release.py with
filelock==3.29.7 on Windows.
-
In the ordinary single-holder case, observe:
filelock_version=3.29.7
exists_while_held=True
exists_after_release=False
delete_observed=True
-
Inspect the constructor and observe that no option disables this cleanup.
Observed vs expected
Observed:
WindowsFileLock always attempts to unlink after release. Callers cannot request
a persistent lock path.
Expected:
An opt-in setting preserves the path while the default retains current cleanup
behavior.
Root cause (verified in source, 3.29.7)
WindowsFileLock._release()
unconditionally attempts Path(self.lock_file).unlink() after unlock and
close.
This is a deliberate behavior restored by PR #511 after issue #509. The gap is
not the default. It is the absence of a caller-selectable stable-path contract.
Suggested fix
Add a keyword-only option such as delete_on_release: bool = True to the native
Windows lock. Preserve True as the compatibility default. When false, skip
the post-close unlink and document that the empty lock file is intentionally
reused across acquisitions.
Include the option in singleton compatibility checks and async construction.
If a cross-platform option is preferable, give each backend an explicit
documented default rather than promising identical cleanup behavior.
Verification
- Default construction retains current best-effort Windows cleanup.
delete_on_release=False preserves the same pathname after ordinary,
nested, forced, and async release.
- Repeated acquisitions reuse the persistent file safely.
- Singleton construction rejects incompatible cleanup policies.
- Existing multi-threaded contention tests continue to preserve mutual
exclusion.
Current workaround
Recreate and reprovision the file after each release, or subclass the private
Windows _release() implementation. Recreating the path cannot preserve file
identity, and subclassing duplicates backend lifecycle logic.
Reproduction script
filelock_windows_delete_on_release.py
"""Show the ordinary WindowsFileLock pathname lifecycle in filelock 3.29.7."""
from __future__ import annotations
import sys
import tempfile
from pathlib import Path
def main() -> int:
if sys.platform != "win32":
print("This reproduction targets WindowsFileLock.")
return 2
import filelock
from filelock import FileLock
with tempfile.TemporaryDirectory() as directory:
path = Path(directory) / "resource.lock"
lock = FileLock(path, timeout=0)
lock.acquire()
exists_while_held = path.exists()
lock.release()
exists_after_release = path.exists()
delete_observed = exists_while_held and not exists_after_release
print(f"filelock_version={filelock.__version__}")
print(f"exists_while_held={exists_while_held}")
print(f"exists_after_release={exists_after_release}")
print(f"delete_observed={delete_observed}")
return 0 if delete_observed else 1
if __name__ == "__main__":
raise SystemExit(main())
Severity: Enhancement (callers that provision a stable lock identity cannot disable best-effort pathname deletion)
Summary
I would like
WindowsFileLockto expose a backward-compatible option thatpreserves the lock-file pathname after release. Version 3.29.7 intentionally
attempts to delete it after closing the descriptor. That behavior is convenient
for cleanup, but some local-filesystem protocols require the same path and file
identity to remain available across acquisitions for ACLs, auditing, or
holder-diagnostic continuity.
Environment
filelock 3.29.71efb8932c08789deb08ad93a91d8996cc36bb9ccWindowsFileLockReproduction
Run the attached
filelock_windows_delete_on_release.pywithfilelock==3.29.7on Windows.In the ordinary single-holder case, observe:
Inspect the constructor and observe that no option disables this cleanup.
Observed vs expected
Observed:
Expected:
Root cause (verified in source, 3.29.7)
WindowsFileLock._release()unconditionally attempts
Path(self.lock_file).unlink()after unlock andclose.
This is a deliberate behavior restored by PR #511 after issue #509. The gap is
not the default. It is the absence of a caller-selectable stable-path contract.
Suggested fix
Add a keyword-only option such as
delete_on_release: bool = Trueto the nativeWindows lock. Preserve
Trueas the compatibility default. When false, skipthe post-close unlink and document that the empty lock file is intentionally
reused across acquisitions.
Include the option in singleton compatibility checks and async construction.
If a cross-platform option is preferable, give each backend an explicit
documented default rather than promising identical cleanup behavior.
Verification
delete_on_release=Falsepreserves the same pathname after ordinary,nested, forced, and async release.
exclusion.
Current workaround
Recreate and reprovision the file after each release, or subclass the private
Windows
_release()implementation. Recreating the path cannot preserve fileidentity, and subclassing duplicates backend lifecycle logic.
Reproduction script
filelock_windows_delete_on_release.py