Repository navigation
🐛 fix(api): release thread holds, guard reentry - #810
Merged
Merged
Conversation
gaborbernat
force-pushed
the
fix-api-release-fds
branch
2 times, most recently
from
October 8, 2026 14:30
8387e53 to
b1bd83e
Compare
gaborbernat
enabled auto-merge (squash)
October 8, 2026 20:10
gaborbernat
force-pushed
the
fix-api-release-fds
branch
from
October 8, 2026 20:12
b1bd83e to
0af89da
Compare
A thread_local=True lock kept each thread's descriptor in a threading.local, so __del__ on another thread found nothing to release and the owning thread's fd and kernel lock leaked for the process lifetime, along with its deadlock-registry entry. ThreadLocalFileContext now keeps each thread's state in a plain FileLockContext the instance tracks per hold. __del__ releases every thread's hold; release(force=True) also releases holds of threads that exited, and leaves holds of running threads alone so a force release cannot strip a live thread's exclusion. release() kept the descriptor set until the backend's unlock returned, so a signal handler calling release() in that window closed the same fd number twice, the second time on whatever file had reused it. A per-context releasing flag makes the nested call a no-op, and the how-to now recommends raising from the handler instead of releasing in it.
gaborbernat
force-pushed
the
fix-api-release-fds
branch
from
October 8, 2026 20:12
0af89da to
3f08430
Compare
gaborbernat
disabled auto-merge
October 8, 2026 20:40
gaborbernat
added a commit
that referenced
this pull request
Oct 8, 2026
A coherence review of the PRs merged since 4.0.12 found failures that come from those PRs or from how they interact. StrictSoftFileLock: an EEXIST link counts as committed when the claim names the file behind the publisher's own descriptor, so a peer reaping the private record no longer orphans the intent (#787, #792). The next acquire from any thread, or the finalizer, finishes a doorway an exited thread left pending. An unparsable lock-path occupant raises once it stays unchanged for two seconds, a failed filesystem-clock probe trusts no age, and the claims property no longer writes a probe. break_lock_file re-checks the marker right before renaming it. SoftReadWriteLock: gen/HEAD carries the epoch and only names a generation that must still read back, a commit refuses a successor whose predecessor compaction freed, and a failed HEAD rename no longer fails a commit that landed (#795, #799). The log and the singleton key go back to 4.0.12's location, so mixed 4.0.12 fleets share one log on a symlinked path again (#801). BaseFileLock: cross-thread force releases take the transition lock, the release guard uses plain stores so a raising signal handler cannot leave it set, and a lease's claim travels with the hold it serves (#810, #791). BaseAsyncFileLock skips path resolution on a re-entrant acquire, and its finalizer falls back to the sync release at interpreter exit and when the scheduled release fails (#800). Docs and changelog: retype the breaking fragments, fix contradictions, and add an upgrade section for mixed 4.0.x fleets.
gaborbernat
added a commit
that referenced
this pull request
Oct 9, 2026
A coherence review of the PRs merged since 4.0.12 found failures that come from those PRs or from how they interact. StrictSoftFileLock: an EEXIST link counts as committed when the claim names the file behind the publisher's own descriptor, so a peer reaping the private record no longer orphans the intent (#787, #792). The next acquire from any thread, or the finalizer, finishes a doorway an exited thread left pending. An unparsable lock-path occupant raises once it stays unchanged for two seconds, a failed filesystem-clock probe trusts no age, and claims no longer probes. break_lock_file re-checks the marker right before renaming it. SoftReadWriteLock: gen/HEAD carries the epoch and only names a generation that must still read back, compaction unlinks oldest first so survivors stay contiguous, a commit refuses a successor whose predecessor is gone before and after its link, HEAD only moves forward, and a failed HEAD rename no longer fails a landed commit (#795, #799). The log and singleton key go back to 4.0.12's location (#801). Heartbeat and poll intervals are bounded by threading.TIMEOUT_MAX, and an interrupted release still leaves. BaseFileLock: cross-thread force releases take the transition lock, the release guard uses plain stores so a raising signal handler cannot leave it set, and a lease's claim travels with its hold (#810, #791). Every lock validates timeouts and intervals the same way, accepts Decimal and Fraction again, deprecates a string timeout in the setter, and compares singleton timeouts by the wait they mean (#803). filelock.version is the version string again (#790). The async layer skips path resolution on a re-entrant acquire and falls back to a sync release when a finalizer's release cannot run (#800). Soft markers: a lease_duration float subclass is recorded as a plain float, a host-namespace contender keeps a marker whose owner still runs in another namespace under the recorded PID and start time, a Timeout names a holder it cannot probe, and a lease heartbeat rides out one missing refresh (#797, #786). ReadWriteLock: probe releases never wait on the table lock, so a GC finalizer cannot deadlock it, a connect reuses an idle probe of its inode instead of opening another, and the async wrapper releases only its own level of a shared singleton (#794, #806). A fork transition finished on another thread clears the thread that entered it. Docs and changelog: fragments corrected, contradictions fixed, and an upgrade section for mixed 4.0.x fleets added.
gaborbernat
added a commit
that referenced
this pull request
Oct 9, 2026
A coherence review of the PRs merged since 4.0.12 found failures that come from those PRs or from how they interact. StrictSoftFileLock: an EEXIST link counts as committed when the claim names the file behind the publisher's own descriptor, so a peer reaping the private record no longer orphans the intent (#787, #792). The next acquire from any thread, or the finalizer, finishes a doorway an exited thread left pending. An unparsable lock-path occupant raises once it stays unchanged for two seconds, a failed filesystem-clock probe trusts no age, and claims no longer probes. break_lock_file re-checks the marker right before renaming it. SoftReadWriteLock: gen/HEAD carries the epoch and only names a generation that must still read back, compaction unlinks oldest first so survivors stay contiguous, a commit refuses a successor whose predecessor is gone before and after its link, HEAD only moves forward, and a failed HEAD rename no longer fails a landed commit (#795, #799). The log and singleton key go back to 4.0.12's location (#801). Heartbeat and poll intervals are bounded by threading.TIMEOUT_MAX, and an interrupted release still leaves. BaseFileLock: cross-thread force releases take the transition lock, the release guard uses plain stores so a raising signal handler cannot leave it set, and a lease's claim travels with its hold (#810, #791). Every lock validates timeouts and intervals the same way, accepts Decimal and Fraction again, deprecates a string timeout in the setter, and compares singleton timeouts by the wait they mean (#803). filelock.version is the version string again (#790). The async layer skips path resolution on a re-entrant acquire and falls back to a sync release when a finalizer's release cannot run (#800). Soft markers: a lease_duration float subclass is recorded as a plain float, a host-namespace contender keeps a marker whose owner still runs in another namespace under the recorded PID and start time, a Timeout names a holder it cannot probe, and a lease heartbeat rides out one missing refresh (#797, #786). ReadWriteLock: probe releases never wait on the table lock, so a GC finalizer cannot deadlock it, a connect reuses an idle probe of its inode instead of opening another, and the async wrapper releases only its own level of a shared singleton (#794, #806). A fork transition finished on another thread clears the thread that entered it. Docs and changelog: fragments corrected, contradictions fixed, and an upgrade section for mixed 4.0.x fleets added.
gaborbernat
added a commit
that referenced
this pull request
Oct 9, 2026
A coherence review of the PRs merged since 4.0.12 found failures that come from those PRs or from how they interact; follow-up reviews found older gaps around interrupted releases and interpreter exit. StrictSoftFileLock: an EEXIST link counts as committed when the claim names the file behind the publisher's own descriptor, so a peer reaping the private record no longer orphans the intent (#787, #792). The next acquire from any thread, or the finalizer, finishes a doorway an exited thread left pending. An unparsable lock-path occupant raises once it stays unchanged for two seconds, a failed filesystem-clock probe trusts no age, and claims no longer probes. break_lock_file re-checks the marker right before renaming it. SoftReadWriteLock: gen/HEAD carries the epoch and only names a generation that must still read back, compaction unlinks oldest first so survivors stay contiguous, a commit refuses a successor whose predecessor is gone before and after its link, HEAD only moves forward, and a failed HEAD rename no longer fails a landed commit (#795, #799). The log and singleton key go back to 4.0.12's location (#801). Heartbeat and poll intervals are bounded by threading.TIMEOUT_MAX, and an interrupted release still leaves. BaseFileLock: cross-thread force releases take the transition lock, and a release a signal handler interrupts stays recoverable on every supported Python: the releasing flag names the releasing frame, the registry entry goes only while it is still ours, a retried release finishes a stale one, and Windows treats a second unlock as done (#810). A lease's claim travels with its hold (#791). Every lock validates timeouts, intervals and lifetime the same way, accepts Decimal and Fraction again, deprecates a string timeout in the setter, and compares singleton timeouts by the wait they mean (#803). filelock.version is the version string again (#790). A lock finalized at exit skips the fork bookkeeping a frozen daemon thread may hold. asyncio: a re-entrant acquire skips path resolution, a finalizer falls back to a sync release when its scheduled one cannot run (#800), a finalized singleton leaves the cache first, and a finalized thread-local lock releases every thread's hold. Soft markers: a lease_duration float subclass is recorded as a plain float, a host-namespace contender keeps a marker whose owner still runs in another namespace under the recorded PID and start time, a Timeout names a holder it cannot probe, and a lease heartbeat rides out one missing refresh (#797, #786). SoftFileLock unlinks its marker before it relinquishes the descriptor, so an interrupted release can be retried; Windows finishes a pending unlink on the next acquire or release. ReadWriteLock: probe releases never wait on the table lock and resume after an interrupt, a connect reuses an idle probe of its inode, and the async wrapper releases only its own level of a shared singleton (#794, #806). On macOS a connect beside a holder goes through a private hard link so SQLite reuses its deferred descriptors. A fork transition finished on another thread clears the thread that entered it. Docs and changelog: every fragment states only the change since 4.0.12, contradictions fixed, and an upgrade section for mixed 4.0.x fleets added.
gaborbernat
added a commit
that referenced
this pull request
Oct 9, 2026
A coherence review of the PRs merged since 4.0.12 found failures that come from those PRs or from how they interact; follow-up reviews found older gaps around interrupted releases and interpreter exit. StrictSoftFileLock: an EEXIST link counts as committed when the claim names the file behind the publisher's own descriptor, so a peer reaping the private record no longer orphans the intent (#787, #792). The next acquire from any thread, or the finalizer, finishes a doorway an exited thread left pending. An unparsable lock-path occupant raises once it stays unchanged for two seconds, a failed filesystem-clock probe trusts no age, and claims no longer probes. break_lock_file re-checks the marker right before renaming it. SoftReadWriteLock: gen/HEAD carries the epoch and only names a generation that must still read back, compaction unlinks oldest first so survivors stay contiguous, a commit refuses a successor whose predecessor is gone before and after its link, HEAD only moves forward, and a failed HEAD rename no longer fails a landed commit (#795, #799). The log and singleton key go back to 4.0.12's location (#801). Heartbeat and poll intervals are bounded by threading.TIMEOUT_MAX, and an interrupted release still leaves. BaseFileLock: cross-thread force releases take the transition lock, and a release a signal handler interrupts stays recoverable on every supported Python: the releasing flag names the releasing frame, the registry entry goes only while it is still ours, a retried release finishes a stale one, and Windows treats a second unlock as done (#810). A lease's claim travels with its hold (#791). Every lock validates timeouts, intervals and lifetime the same way, accepts Decimal and Fraction again, deprecates a string timeout in the setter, and compares singleton timeouts by the wait they mean (#803). filelock.version is the version string again (#790). A lock finalized at exit skips the fork bookkeeping a frozen daemon thread may hold. asyncio: a re-entrant acquire skips path resolution, a finalizer falls back to a sync release when its scheduled one cannot run (#800), a finalized singleton leaves the cache first, and a finalized thread-local lock releases every thread's hold. Soft markers: a lease_duration float subclass is recorded as a plain float, a host-namespace contender keeps a marker whose owner still runs in another namespace under the recorded PID and start time, a Timeout names a holder it cannot probe, and a lease heartbeat rides out one missing refresh (#797, #786). SoftFileLock unlinks its marker before it relinquishes the descriptor, so an interrupted release can be retried; Windows finishes a pending unlink on the next acquire or release. ReadWriteLock: probe releases never wait on the table lock and resume after an interrupt, a connect reuses an idle probe of its inode, and the async wrapper releases only its own level of a shared singleton (#794, #806). On macOS a connect beside a holder goes through a private hard link so SQLite reuses its deferred descriptors. A fork transition finished on another thread clears the thread that entered it. Docs and changelog: every fragment states only the change since 4.0.12, contradictions fixed, and an upgrade section for mixed 4.0.x fleets added.
gaborbernat
added a commit
that referenced
this pull request
Oct 9, 2026
A coherence review of the PRs merged since 4.0.12 found failures that come from those PRs or from how they interact; follow-up reviews found older gaps around interrupted releases and interpreter exit. StrictSoftFileLock: an EEXIST link counts as committed when the claim names the file behind the publisher's own descriptor, so a peer reaping the private record no longer orphans the intent (#787, #792). The next acquire from any thread, or the finalizer, finishes a doorway an exited thread left pending. An unparsable lock-path occupant raises once it stays unchanged for two seconds, a failed filesystem-clock probe trusts no age, and claims no longer probes. break_lock_file re-checks the marker right before renaming it. SoftReadWriteLock: gen/HEAD carries the epoch and only names a generation that must still read back, compaction unlinks oldest first so survivors stay contiguous, a commit refuses a successor whose predecessor is gone before and after its link, HEAD only moves forward, and a failed HEAD rename no longer fails a landed commit (#795, #799). The log and singleton key go back to 4.0.12's location (#801). Heartbeat and poll intervals are bounded by threading.TIMEOUT_MAX, and an interrupted release still leaves. BaseFileLock: cross-thread force releases take the transition lock, and a release a signal handler interrupts stays recoverable on every supported Python: the releasing flag names the releasing frame, the registry entry goes only while it is still ours, a retried release finishes a stale one, and Windows treats a second unlock as done (#810). A lease's claim travels with its hold (#791). Every lock validates timeouts, intervals and lifetime the same way, accepts Decimal and Fraction again, deprecates a string timeout in the setter, and compares singleton timeouts by the wait they mean (#803). filelock.version is the version string again (#790). A lock finalized at exit skips the fork bookkeeping a frozen daemon thread may hold. asyncio: a re-entrant acquire skips path resolution, a finalizer falls back to a sync release when its scheduled one cannot run (#800), a finalized singleton leaves the cache first, and a finalized thread-local lock releases every thread's hold. Soft markers: a lease_duration float subclass is recorded as a plain float, a host-namespace contender keeps a marker whose owner still runs in another namespace under the recorded PID and start time, a Timeout names a holder it cannot probe, and a lease heartbeat rides out one missing refresh (#797, #786). SoftFileLock unlinks its marker before it relinquishes the descriptor, so an interrupted release can be retried; Windows finishes a pending unlink on the next acquire or release. ReadWriteLock: probe releases never wait on the table lock and resume after an interrupt, a connect reuses an idle probe of its inode, and the async wrapper releases only its own level of a shared singleton (#794, #806). On macOS a connect beside a holder goes through a private hard link so SQLite reuses its deferred descriptors. A fork transition finished on another thread clears the thread that entered it. Docs and changelog: every fragment states only the change since 4.0.12, contradictions fixed, and an upgrade section for mixed 4.0.x fleets added.
gaborbernat
added a commit
that referenced
this pull request
Oct 9, 2026
A coherence review of the PRs merged since 4.0.12 found failures that come from those PRs or from how they interact; follow-up reviews found older gaps around interrupted releases and interpreter exit. StrictSoftFileLock: an EEXIST link counts as committed when the claim names the file behind the publisher's own descriptor, so a peer reaping the private record no longer orphans the intent (#787, #792). The next acquire from any thread, or the finalizer, finishes a doorway an exited thread left pending. An unparsable lock-path occupant raises once it stays unchanged for two seconds, a failed filesystem-clock probe trusts no age, and claims no longer probes. break_lock_file re-checks the marker right before renaming it. SoftReadWriteLock: gen/HEAD carries the epoch and only names a generation that must still read back, compaction unlinks oldest first so survivors stay contiguous, a commit refuses a successor whose predecessor is gone before and after its link, HEAD only moves forward, and a failed HEAD rename no longer fails a landed commit (#795, #799). The log and singleton key go back to 4.0.12's location (#801). Heartbeat and poll intervals are bounded by threading.TIMEOUT_MAX, and an interrupted release still leaves. BaseFileLock: cross-thread force releases take the transition lock, and a release a signal handler interrupts stays recoverable on every supported Python: the releasing flag names the releasing frame, the registry entry goes only while it is still ours, a retried release finishes a stale one, and Windows treats a second unlock as done (#810). A lease's claim travels with its hold (#791). Every lock validates timeouts, intervals and lifetime the same way, accepts Decimal and Fraction again, deprecates a string timeout in the setter, and compares singleton timeouts by the wait they mean (#803). filelock.version is the version string again (#790). A lock finalized at exit skips the fork bookkeeping a frozen daemon thread may hold. asyncio: a re-entrant acquire skips path resolution, a finalizer falls back to a sync release when its scheduled one cannot run (#800), a finalized singleton leaves the cache first, and a finalized thread-local lock releases every thread's hold. Soft markers: a lease_duration float subclass is recorded as a plain float, a host-namespace contender keeps a marker whose owner still runs in another namespace under the recorded PID and start time, a Timeout names a holder it cannot probe, and a lease heartbeat rides out one missing refresh (#797, #786). SoftFileLock unlinks its marker before it relinquishes the descriptor, so an interrupted release can be retried; Windows finishes a pending unlink on the next acquire or release. ReadWriteLock: probe releases never wait on the table lock and resume after an interrupt, a connect reuses an idle probe of its inode, and the async wrapper releases only its own level of a shared singleton (#794, #806). On macOS a connect beside a holder goes through a private hard link so SQLite reuses its deferred descriptors. A fork transition finished on another thread clears the thread that entered it. Docs and changelog: every fragment states only the change since 4.0.12, contradictions fixed, and an upgrade section for mixed 4.0.x fleets added.
gaborbernat
added a commit
that referenced
this pull request
Oct 9, 2026
A coherence review of the PRs merged since 4.0.12 found failures that come from those PRs or from how they interact; follow-up reviews found older gaps around interrupted releases and interpreter exit. StrictSoftFileLock: an EEXIST link counts as committed when the claim names the file behind the publisher's own descriptor, so a peer reaping the private record no longer orphans the intent (#787, #792). The next acquire from any thread, or the finalizer, finishes a doorway an exited thread left pending. An unparsable lock-path occupant raises once it stays unchanged for two seconds, a failed filesystem-clock probe trusts no age, and claims no longer probes. break_lock_file re-checks the marker right before renaming it. SoftReadWriteLock: gen/HEAD carries the epoch and only names a generation that must still read back, compaction unlinks oldest first so survivors stay contiguous, a commit refuses a successor whose predecessor is gone before and after its link, HEAD only moves forward, and a failed HEAD rename no longer fails a landed commit (#795, #799). The log and singleton key go back to 4.0.12's location (#801). Heartbeat and poll intervals are bounded by threading.TIMEOUT_MAX, and an interrupted release still leaves. BaseFileLock: cross-thread force releases take the transition lock, and a release a signal handler interrupts stays recoverable on every supported Python: the releasing flag names the releasing frame, the registry entry goes only while it is still ours, a retried release finishes a stale one, and Windows treats a second unlock as done (#810). A lease's claim travels with its hold (#791). Every lock validates timeouts, intervals and lifetime the same way, accepts Decimal and Fraction again, deprecates a string timeout in the setter, and compares singleton timeouts by the wait they mean (#803). filelock.version is the version string again (#790). A lock finalized at exit skips the fork bookkeeping a frozen daemon thread may hold. asyncio: a re-entrant acquire skips path resolution, a finalizer falls back to a sync release when its scheduled one cannot run (#800), a finalized singleton leaves the cache first, and a finalized thread-local lock releases every thread's hold. Soft markers: a lease_duration float subclass is recorded as a plain float, a host-namespace contender keeps a marker whose owner still runs in another namespace under the recorded PID and start time, a Timeout names a holder it cannot probe, and a lease heartbeat rides out one missing refresh (#797, #786). SoftFileLock unlinks its marker before it relinquishes the descriptor, so an interrupted release can be retried; Windows finishes a pending unlink on the next acquire or release. ReadWriteLock: probe releases never wait on the table lock and resume after an interrupt, a connect reuses an idle probe of its inode, and the async wrapper releases only its own level of a shared singleton (#794, #806). On macOS a connect beside a holder goes through a private hard link so SQLite reuses its deferred descriptors. A fork transition finished on another thread clears the thread that entered it. Docs and changelog: every fragment states only the change since 4.0.12, contradictions fixed, and an upgrade section for mixed 4.0.x fleets added.
gaborbernat
added a commit
that referenced
this pull request
Oct 9, 2026
A coherence review of the PRs merged since 4.0.12 found failures that come from those PRs or from how they interact; follow-up reviews found older gaps around interrupted releases and interpreter exit. StrictSoftFileLock: an EEXIST link counts as committed when the claim names the file behind the publisher's own descriptor, so a peer reaping the private record no longer orphans the intent (#787, #792). The next acquire from any thread, or the finalizer, finishes a doorway an exited thread left pending. An unparsable lock-path occupant raises once it stays unchanged for two seconds, a failed filesystem-clock probe trusts no age, and claims no longer probes. break_lock_file re-checks the marker right before renaming it. SoftReadWriteLock: gen/HEAD carries the epoch and only names a generation that must still read back, compaction unlinks oldest first so survivors stay contiguous, a commit refuses a successor whose predecessor is gone before and after its link, HEAD only moves forward, and a failed HEAD rename no longer fails a landed commit (#795, #799). The log and singleton key go back to 4.0.12's location (#801). Heartbeat and poll intervals are bounded by threading.TIMEOUT_MAX, and an interrupted release still leaves. BaseFileLock: cross-thread force releases take the transition lock, and a release a signal handler interrupts stays recoverable on every supported Python: the releasing flag names the releasing frame, the registry entry goes only while it is still ours, a retried release finishes a stale one, and Windows treats a second unlock as done (#810). A lease's claim travels with its hold (#791). Every lock validates timeouts, intervals and lifetime the same way, accepts Decimal and Fraction again, deprecates a string timeout in the setter, and compares singleton timeouts by the wait they mean (#803). filelock.version is the version string again (#790). A lock finalized at exit skips the fork bookkeeping a frozen daemon thread may hold. asyncio: a re-entrant acquire skips path resolution, a finalizer falls back to a sync release when its scheduled one cannot run (#800), a finalized singleton leaves the cache first, and a finalized thread-local lock releases every thread's hold. Soft markers: a lease_duration float subclass is recorded as a plain float, a host-namespace contender keeps a marker whose owner still runs in another namespace under the recorded PID and start time, a Timeout names a holder it cannot probe, and a lease heartbeat rides out one missing refresh (#797, #786). SoftFileLock unlinks its marker before it relinquishes the descriptor, so an interrupted release can be retried; Windows finishes a pending unlink on the next acquire or release. ReadWriteLock: probe releases never wait on the table lock and resume after an interrupt, a connect reuses an idle probe of its inode, and the async wrapper releases only its own level of a shared singleton (#794, #806). On macOS a connect beside a holder goes through a private hard link so SQLite reuses its deferred descriptors. A fork transition finished on another thread clears the thread that entered it. Docs and changelog: every fragment states only the change since 4.0.12, contradictions fixed, and an upgrade section for mixed 4.0.x fleets added.
gaborbernat
added a commit
that referenced
this pull request
Oct 9, 2026
A coherence review of the PRs merged since 4.0.12 found failures that come from those PRs or from how they interact; follow-up reviews found older gaps around interrupted releases and interpreter exit. StrictSoftFileLock: an EEXIST link counts as committed when the claim names the file behind the publisher's own descriptor, so a peer reaping the private record no longer orphans the intent (#787, #792). The next acquire from any thread, or the finalizer, finishes a doorway an exited thread left pending. An unparsable lock-path occupant raises once it stays unchanged for two seconds, a failed filesystem-clock probe trusts no age, and claims no longer probes. break_lock_file re-checks the marker right before renaming it. SoftReadWriteLock: gen/HEAD carries the epoch and only names a generation that must still read back, compaction unlinks oldest first so survivors stay contiguous, a commit refuses a successor whose predecessor is gone before and after its link, HEAD only moves forward, and a failed HEAD rename no longer fails a landed commit (#795, #799). The log and singleton key go back to 4.0.12's location (#801). Heartbeat and poll intervals are bounded by threading.TIMEOUT_MAX, and an interrupted release still leaves. BaseFileLock: cross-thread force releases take the transition lock, and a release a signal handler interrupts stays recoverable on every supported Python: the releasing flag names the releasing frame, the registry entry goes only while it is still ours, a retried release finishes a stale one, and Windows treats a second unlock as done (#810). A lease's claim travels with its hold (#791). Every lock validates timeouts, intervals and lifetime the same way, accepts Decimal and Fraction again, deprecates a string timeout in the setter, and compares singleton timeouts by the wait they mean (#803). filelock.version is the version string again (#790). A lock finalized at exit skips the fork bookkeeping a frozen daemon thread may hold. asyncio: a re-entrant acquire skips path resolution, a finalizer falls back to a sync release when its scheduled one cannot run (#800), a finalized singleton leaves the cache first, and a finalized thread-local lock releases every thread's hold. Soft markers: a lease_duration float subclass is recorded as a plain float, a host-namespace contender keeps a marker whose owner still runs in another namespace under the recorded PID and start time, a Timeout names a holder it cannot probe, and a lease heartbeat rides out one missing refresh (#797, #786). SoftFileLock unlinks its marker before it relinquishes the descriptor, so an interrupted release can be retried; Windows finishes a pending unlink on the next acquire or release. ReadWriteLock: probe releases never wait on the table lock and resume after an interrupt, a connect reuses an idle probe of its inode, and the async wrapper releases only its own level of a shared singleton (#794, #806). On macOS a connect beside a holder goes through a private hard link so SQLite reuses its deferred descriptors. A fork transition finished on another thread clears the thread that entered it. Docs and changelog: every fragment states only the change since 4.0.12, contradictions fixed, and an upgrade section for mixed 4.0.x fleets added.
gaborbernat
added a commit
that referenced
this pull request
Oct 9, 2026
A coherence review of the PRs merged since 4.0.12 found failures that come from those PRs or from how they interact; follow-up reviews found older gaps around interrupted releases and interpreter exit. StrictSoftFileLock: an EEXIST link counts as committed when the claim names the file behind the publisher's own descriptor, so a peer reaping the private record no longer orphans the intent (#787, #792). The next acquire from any thread, or the finalizer, finishes a doorway an exited thread left pending. An unparsable lock-path occupant raises once it stays unchanged for two seconds, a failed filesystem-clock probe trusts no age, and claims no longer probes. break_lock_file re-checks the marker right before renaming it. SoftReadWriteLock: gen/HEAD carries the epoch and only names a generation that must still read back, compaction unlinks oldest first so survivors stay contiguous, a commit refuses a successor whose predecessor is gone before and after its link, HEAD only moves forward, and a failed HEAD rename no longer fails a landed commit (#795, #799). HEAD, a hint readers verify, is no longer flushed, which halves the flushes per commit; a torn one counts as missing. The log and singleton key go back to 4.0.12's location (#801). Heartbeat and poll intervals are bounded by threading.TIMEOUT_MAX, and an interrupted release still leaves. BaseFileLock: cross-thread force releases take the transition lock, and a release a signal handler interrupts stays recoverable on every supported Python: the releasing flag names the releasing frame, the registry entry goes only while it is still ours, a retried release finishes a stale one, and Windows treats a second unlock as done (#810). A lease's claim travels with its hold (#791). Every lock validates timeouts, intervals and lifetime the same way, accepts Decimal and Fraction again, deprecates a string timeout in the setter, and compares singleton timeouts by the wait they mean (#803). filelock.version is the version string again (#790). A lock finalized at exit skips the fork bookkeeping a frozen daemon thread may hold. asyncio: a re-entrant acquire skips path resolution, a finalizer falls back to a sync release when its scheduled one cannot run (#800), a finalized singleton leaves the cache first, and a finalized thread-local lock releases every thread's hold. Soft markers: a lease_duration float subclass is recorded as a plain float, a host-namespace contender keeps a marker whose owner still runs in another namespace under the recorded PID and start time, a Timeout names a holder it cannot probe, and a lease heartbeat rides out one missing refresh (#797, #786). SoftFileLock unlinks its marker before it relinquishes the descriptor, so an interrupted release can be retried; Windows finishes a pending unlink on the next acquire or release. ReadWriteLock: probe releases never wait on the table lock and resume after an interrupt, a connect reuses an idle probe of its inode, and the async wrapper releases only its own level of a shared singleton (#794, #806). On macOS a connect beside a holder goes through a private hard link so SQLite reuses its deferred descriptors. A fork transition finished on another thread clears the thread that entered it. Docs and changelog: every fragment states only the change since 4.0.12, contradictions fixed, and an upgrade section for mixed 4.0.x fleets added.
gaborbernat
added a commit
that referenced
this pull request
Oct 9, 2026
A coherence review of the PRs merged since 4.0.12 found failures that come from those PRs or from how they interact; follow-up reviews found older gaps around interrupted releases and interpreter exit. StrictSoftFileLock: an EEXIST link counts as committed when the claim names the file behind the publisher's own descriptor, so a peer reaping the private record no longer orphans the intent (#787, #792). The next acquire from any thread, or the finalizer, finishes a doorway an exited thread left pending. An unparsable lock-path occupant raises once it stays unchanged for two seconds, a failed filesystem-clock probe trusts no age, and claims no longer probes. break_lock_file re-checks the marker right before renaming it. SoftReadWriteLock: gen/HEAD carries the epoch and only names a generation that must still read back, compaction unlinks oldest first so survivors stay contiguous, a commit refuses a successor whose predecessor is gone before and after its link, HEAD only moves forward, and a failed HEAD rename no longer fails a landed commit (#795, #799). HEAD, a hint readers verify, is no longer flushed, which halves the flushes per commit; a torn one counts as missing. The log and singleton key go back to 4.0.12's location (#801). Heartbeat and poll intervals are bounded by threading.TIMEOUT_MAX, and an interrupted release still leaves. BaseFileLock: cross-thread force releases take the transition lock, and a release a signal handler interrupts stays recoverable on every supported Python: the releasing flag names the releasing frame, the registry entry goes only while it is still ours, a retried release finishes a stale one, and Windows treats a second unlock as done (#810). A lease's claim travels with its hold (#791). Every lock validates timeouts, intervals and lifetime the same way, accepts Decimal and Fraction again, deprecates a string timeout in the setter, and compares singleton timeouts by the wait they mean (#803). filelock.version is the version string again (#790). A lock finalized at exit skips the fork bookkeeping a frozen daemon thread may hold, an acquire a signal handler starts mid-acquire raises instead of hanging, and a value too small for a float keeps its sign. asyncio: a re-entrant acquire skips path resolution, a finalizer falls back to a sync release when its scheduled one cannot run (#800), a finalized singleton leaves the cache first, and a finalized thread-local lock releases every thread's hold. Soft markers: a lease_duration float subclass is recorded as a plain float, a host-namespace contender keeps a marker whose owner still runs in another namespace under the recorded PID and start time, a Timeout names a holder it cannot probe, and a lease heartbeat rides out one missing refresh (#797, #786). SoftFileLock unlinks its marker before it relinquishes the descriptor, so an interrupted release can be retried; Windows finishes a pending unlink on the next acquire or release and takes and closes the pending descriptor in one C call chain. ReadWriteLock: probe releases never wait on the table lock and resume after an interrupt, a connect reuses an idle probe of its inode, and the async wrapper releases only its own level of a shared singleton (#794, #806). On macOS a connect beside a holder goes through a private hard link so SQLite reuses its deferred descriptors; link directories carry their owner in the name, and the first link beside a database removes those of dead processes. A connect lists its probe before leasing it, so an interrupt cannot pin the inode's probes. A fork transition finished on another thread clears the thread that entered it. Docs and changelog: every fragment states only the change since 4.0.12, contradictions fixed, and an upgrade section for mixed 4.0.x fleets added.
gaborbernat
added a commit
that referenced
this pull request
Oct 9, 2026
A coherence review of the PRs merged since 4.0.12 found failures that come from those PRs or from how they interact; follow-up reviews found older gaps around interrupted releases and interpreter exit. StrictSoftFileLock: an EEXIST link counts as committed when the claim names the file behind the publisher's own descriptor, so a peer reaping the private record no longer orphans the intent (#787, #792). The next acquire from any thread, or the finalizer, finishes a doorway an exited thread left pending. An unparsable lock-path occupant raises once it stays unchanged for two seconds, a failed filesystem-clock probe trusts no age, and claims no longer probes. break_lock_file re-checks the marker right before renaming it. SoftReadWriteLock: gen/HEAD carries the epoch and only names a generation that must still read back, compaction unlinks oldest first so survivors stay contiguous, a commit refuses a successor whose predecessor is gone before and after its link, HEAD only moves forward, and a failed HEAD rename no longer fails a landed commit (#795, #799). HEAD, a hint readers verify, is no longer flushed, which halves the flushes per commit; a torn one counts as missing. The log and singleton key go back to 4.0.12's location (#801). Heartbeat and poll intervals are bounded by threading.TIMEOUT_MAX, and an interrupted release still leaves. BaseFileLock: cross-thread force releases take the transition lock, and a release a signal handler interrupts stays recoverable on every supported Python: the releasing flag names the releasing frame, the registry entry goes only while it is still ours, a retried release finishes a stale one, and Windows treats a second unlock as done (#810). A lease's claim travels with its hold (#791). Every lock validates timeouts, intervals and lifetime the same way, accepts Decimal and Fraction again, deprecates a string timeout in the setter, and compares singleton timeouts by the wait they mean (#803). filelock.version is the version string again (#790). A lock finalized at exit skips the fork bookkeeping a frozen daemon thread may hold, an acquire a signal handler starts mid-acquire raises instead of hanging, and a value too small for a float keeps its sign. asyncio: a re-entrant acquire skips path resolution, a finalizer falls back to a sync release when its scheduled one cannot run (#800), a finalized singleton leaves the cache first, and a finalized thread-local lock releases every thread's hold. Soft markers: a lease_duration float subclass is recorded as a plain float, a host-namespace contender keeps a marker whose owner still runs in another namespace under the recorded PID and start time, a Timeout names a holder it cannot probe, and a lease heartbeat rides out one missing refresh (#797, #786). SoftFileLock unlinks its marker before it relinquishes the descriptor, so an interrupted release can be retried; Windows finishes a pending unlink on the next acquire or release and takes and closes the pending descriptor in one C call chain. ReadWriteLock: probe releases never wait on the table lock and resume after an interrupt, a connect reuses an idle probe of its inode, and the async wrapper releases only its own level of a shared singleton (#794, #806). On macOS a connect beside a holder goes through a private hard link so SQLite reuses its deferred descriptors; link directories carry their owner in the name, and the first link beside a database removes those of dead processes. A connect lists its probe before leasing it, so an interrupt cannot pin the inode's probes. A fork transition finished on another thread clears the thread that entered it. Docs and changelog: every fragment states only the change since 4.0.12, contradictions fixed, and an upgrade section for mixed 4.0.x fleets added.
gaborbernat
added a commit
that referenced
this pull request
Oct 9, 2026
A coherence review of the PRs merged since 4.0.12 found failures that come from those PRs or from how they interact; follow-up reviews found older gaps around interrupted releases and interpreter exit. StrictSoftFileLock: an EEXIST link counts as committed when the claim names the file behind the publisher's own descriptor, so a peer reaping the private record no longer orphans the intent (#787, #792). The next acquire from any thread, or the finalizer, finishes a doorway an exited thread left pending. An unparsable lock-path occupant raises once it stays unchanged for two seconds, a failed filesystem-clock probe trusts no age, and claims no longer probes. break_lock_file re-checks the marker right before renaming it. SoftReadWriteLock: gen/HEAD carries the epoch and only names a generation that must still read back, compaction unlinks oldest first so survivors stay contiguous, a commit refuses a successor whose predecessor is gone before and after its link, HEAD only moves forward, and a failed HEAD rename no longer fails a landed commit (#795, #799). HEAD, a hint readers verify, is no longer flushed, which halves the flushes per commit; a torn one counts as missing. The log and singleton key go back to 4.0.12's location (#801). Heartbeat and poll intervals are bounded by threading.TIMEOUT_MAX, and an interrupted release still leaves. BaseFileLock: cross-thread force releases take the transition lock, and a release a signal handler interrupts stays recoverable on every supported Python: the releasing flag names the releasing frame, the registry entry goes only while it is still ours, a retried release finishes a stale one, and Windows treats a second unlock as done (#810). A lease's claim travels with its hold (#791). Every lock validates timeouts, intervals and lifetime the same way, accepts Decimal and Fraction again, deprecates a string timeout in the setter, and compares singleton timeouts by the wait they mean (#803). filelock.version is the version string again (#790). A lock finalized at exit skips the fork bookkeeping a frozen daemon thread may hold, an acquire a signal handler starts mid-acquire raises instead of hanging, and a value too small for a float keeps its sign. asyncio: a re-entrant acquire skips path resolution, a finalizer falls back to a sync release when its scheduled one cannot run (#800), a finalized singleton leaves the cache first, and a finalized thread-local lock releases every thread's hold. Soft markers: a lease_duration float subclass is recorded as a plain float, a host-namespace contender keeps a marker whose owner still runs in another namespace under the recorded PID and start time, a Timeout names a holder it cannot probe, and a lease heartbeat rides out one missing refresh (#797, #786). SoftFileLock unlinks its marker before it relinquishes the descriptor, so an interrupted release can be retried; Windows finishes a pending unlink on the next acquire or release and takes and closes the pending descriptor in one C call chain. ReadWriteLock: probe releases never wait on the table lock and resume after an interrupt, a connect reuses an idle probe of its inode, and the async wrapper releases only its own level of a shared singleton (#794, #806). On macOS a connect beside a holder goes through a private hard link so SQLite reuses its deferred descriptors; link directories carry their owner in the name, and the first link beside a database removes those of dead processes. A connect lists its probe before leasing it, so an interrupt cannot pin the inode's probes. A fork transition finished on another thread clears the thread that entered it. Docs and changelog: every fragment states only the change since 4.0.12, contradictions fixed, and an upgrade section for mixed 4.0.x fleets added.
gaborbernat
added a commit
that referenced
this pull request
Oct 9, 2026
A coherence review of the PRs merged since 4.0.12 found failures that come from those PRs or from how they interact; follow-up reviews found older gaps around interrupted releases and interpreter exit. StrictSoftFileLock: an EEXIST link counts as committed when the claim names the file behind the publisher's own descriptor, so a peer reaping the private record no longer orphans the intent (#787, #792). The next acquire from any thread, or the finalizer, finishes a doorway an exited thread left pending. An unparsable lock-path occupant raises once it stays unchanged for two seconds, a failed filesystem-clock probe trusts no age, and claims no longer probes. break_lock_file re-checks the marker right before renaming it. SoftReadWriteLock: gen/HEAD carries the epoch and only names a generation that must still read back, compaction unlinks oldest first so survivors stay contiguous, a commit refuses a successor whose predecessor is gone before and after its link, HEAD only moves forward, and a failed HEAD rename no longer fails a landed commit (#795, #799). HEAD, a hint readers verify, is no longer flushed, which halves the flushes per commit; a torn one counts as missing. The log and singleton key go back to 4.0.12's location (#801). Heartbeat and poll intervals are bounded by threading.TIMEOUT_MAX, and an interrupted release still leaves. BaseFileLock: cross-thread force releases take the transition lock, and a release a signal handler interrupts stays recoverable on every supported Python: the releasing flag names the releasing frame, the registry entry goes only while it is still ours, a retried release finishes a stale one, and Windows treats a second unlock as done (#810). A lease's claim travels with its hold (#791). Every lock validates timeouts, intervals and lifetime the same way, accepts Decimal and Fraction again, deprecates a string timeout in the setter, and compares singleton timeouts by the wait they mean (#803). filelock.version is the version string again (#790). A lock finalized at exit skips the fork bookkeeping a frozen daemon thread may hold, an acquire a signal handler starts mid-acquire raises instead of hanging, and a value too small for a float keeps its sign. asyncio: a re-entrant acquire skips path resolution, a finalizer falls back to a sync release when its scheduled one cannot run (#800), a finalized singleton leaves the cache first, and a finalized thread-local lock releases every thread's hold. Soft markers: a lease_duration float subclass is recorded as a plain float, a host-namespace contender keeps a marker whose owner still runs in another namespace under the recorded PID and start time, a Timeout names a holder it cannot probe, and a lease heartbeat rides out one missing refresh (#797, #786). SoftFileLock unlinks its marker before it relinquishes the descriptor, so an interrupted release can be retried; Windows finishes a pending unlink on the next acquire or release and takes and closes the pending descriptor in one C call chain. ReadWriteLock: probe releases never wait on the table lock and resume after an interrupt, a connect reuses an idle probe of its inode, and the async wrapper releases only its own level of a shared singleton (#794, #806). On macOS a connect beside a holder goes through a private hard link so SQLite reuses its deferred descriptors; link directories carry their owner in the name, and the first link beside a database removes those of dead processes. A connect lists its probe before leasing it, so an interrupt cannot pin the inode's probes. A fork transition finished on another thread clears the thread that entered it. Docs and changelog: every fragment states only the change since 4.0.12, contradictions fixed, and an upgrade section for mixed 4.0.x fleets added.
gaborbernat
added a commit
that referenced
this pull request
Oct 9, 2026
A coherence review of the PRs merged since 4.0.12 found failures that come from those PRs or from how they interact; follow-up reviews found older gaps around interrupted releases and interpreter exit. StrictSoftFileLock: an EEXIST link counts as committed when the claim names the file behind the publisher's own descriptor, so a peer reaping the private record no longer orphans the intent (#787, #792). The next acquire from any thread, or the finalizer, finishes a doorway an exited thread left pending. An unparsable lock-path occupant raises once it stays unchanged for two seconds, a failed filesystem-clock probe trusts no age, and claims no longer probes. break_lock_file re-checks the marker right before renaming it. SoftReadWriteLock: gen/HEAD carries the epoch and only names a generation that must still read back, compaction unlinks oldest first so survivors stay contiguous, a commit refuses a successor whose predecessor is gone before and after its link, HEAD only moves forward, and a failed HEAD rename no longer fails a landed commit (#795, #799). HEAD, a hint readers verify, is no longer flushed, which halves the flushes per commit; a torn one counts as missing. The log and singleton key go back to 4.0.12's location (#801). Heartbeat and poll intervals are bounded by threading.TIMEOUT_MAX, and an interrupted release still leaves. BaseFileLock: cross-thread force releases take the transition lock, and a release a signal handler interrupts stays recoverable on every supported Python: the releasing flag names the releasing frame, the registry entry goes only while it is still ours, a retried release finishes a stale one, and Windows treats a second unlock as done (#810). A lease's claim travels with its hold (#791). Every lock validates timeouts, intervals and lifetime the same way, accepts Decimal and Fraction again, deprecates a string timeout in the setter, and compares singleton timeouts by the wait they mean (#803). filelock.version is the version string again (#790). A lock finalized at exit skips the fork bookkeeping a frozen daemon thread may hold, an acquire a signal handler starts mid-acquire raises instead of hanging, and a value too small for a float keeps its sign. asyncio: a re-entrant acquire skips path resolution, a finalizer falls back to a sync release when its scheduled one cannot run (#800), a finalized singleton leaves the cache first, and a finalized thread-local lock releases every thread's hold. Soft markers: a lease_duration float subclass is recorded as a plain float, a host-namespace contender keeps a marker whose owner still runs in another namespace under the recorded PID and start time, a Timeout names a holder it cannot probe, and a lease heartbeat rides out one missing refresh (#797, #786). SoftFileLock unlinks its marker before it relinquishes the descriptor, so an interrupted release can be retried; Windows finishes a pending unlink on the next acquire or release and takes and closes the pending descriptor in one C call chain. ReadWriteLock: probe releases never wait on the table lock and resume after an interrupt, a connect reuses an idle probe of its inode, and the async wrapper releases only its own level of a shared singleton (#794, #806). On macOS a connect beside a holder goes through a private hard link so SQLite reuses its deferred descriptors; link directories carry their owner in the name, and the first link beside a database removes those of dead processes. A connect lists its probe before leasing it, so an interrupt cannot pin the inode's probes. A fork transition finished on another thread clears the thread that entered it. Docs and changelog: every fragment states only the change since 4.0.12, contradictions fixed, and an upgrade section for mixed 4.0.x fleets added.
gaborbernat
added a commit
that referenced
this pull request
Oct 9, 2026
A coherence review of the PRs merged since 4.0.12 found failures that come from those PRs or from how they interact; follow-up reviews found older gaps around interrupted releases and interpreter exit. StrictSoftFileLock: an EEXIST link counts as committed when the claim names the file behind the publisher's own descriptor, so a peer reaping the private record no longer orphans the intent (#787, #792). The next acquire from any thread, or the finalizer, finishes a doorway an exited thread left pending. An unparsable lock-path occupant raises once it stays unchanged for two seconds, a failed filesystem-clock probe trusts no age, and claims no longer probes. break_lock_file re-checks the marker right before renaming it. SoftReadWriteLock: gen/HEAD carries the epoch and only names a generation that must still read back, compaction unlinks oldest first so survivors stay contiguous, a commit refuses a successor whose predecessor is gone before and after its link, HEAD only moves forward, and a failed HEAD rename no longer fails a landed commit (#795, #799). HEAD, a hint readers verify, is no longer flushed, which halves the flushes per commit; a torn one counts as missing. The log and singleton key go back to 4.0.12's location (#801). Heartbeat and poll intervals are bounded by threading.TIMEOUT_MAX, and an interrupted release still leaves. BaseFileLock: cross-thread force releases take the transition lock, and a release a signal handler interrupts stays recoverable on every supported Python: the releasing flag names the releasing frame, the registry entry goes only while it is still ours, a retried release finishes a stale one, and Windows treats a second unlock as done (#810). A lease's claim travels with its hold (#791). Every lock validates timeouts, intervals and lifetime the same way, accepts Decimal and Fraction again, deprecates a string timeout in the setter, and compares singleton timeouts by the wait they mean (#803). filelock.version is the version string again (#790). A lock finalized at exit skips the fork bookkeeping a frozen daemon thread may hold, an acquire a signal handler starts mid-acquire raises instead of hanging, and a value too small for a float keeps its sign. asyncio: a re-entrant acquire skips path resolution, a finalizer falls back to a sync release when its scheduled one cannot run (#800), a finalized singleton leaves the cache first, and a finalized thread-local lock releases every thread's hold. Soft markers: a lease_duration float subclass is recorded as a plain float, a host-namespace contender keeps a marker whose owner still runs in another namespace under the recorded PID and start time, a Timeout names a holder it cannot probe, and a lease heartbeat rides out one missing refresh (#797, #786). SoftFileLock unlinks its marker before it relinquishes the descriptor, so an interrupted release can be retried; Windows finishes a pending unlink on the next acquire or release and takes and closes the pending descriptor in one C call chain. ReadWriteLock: probe releases never wait on the table lock and resume after an interrupt, a connect reuses an idle probe of its inode, and the async wrapper releases only its own level of a shared singleton (#794, #806). On macOS a connect beside a holder goes through a private hard link so SQLite reuses its deferred descriptors; link directories carry their owner in the name, and the first link beside a database removes those of dead processes. A connect lists its probe before leasing it, so an interrupt cannot pin the inode's probes. A fork transition finished on another thread clears the thread that entered it. Docs and changelog: every fragment states only the change since 4.0.12, and the contradictions the review listed are fixed.
gaborbernat
added a commit
that referenced
this pull request
Oct 9, 2026
A coherence review of the PRs merged since 4.0.12 found failures that come from those PRs or from how they interact; follow-up reviews found older gaps around interrupted releases and interpreter exit. StrictSoftFileLock: an EEXIST link counts as committed when the claim names the file behind the publisher's own descriptor, so a peer reaping the private record no longer orphans the intent (#787, #792). The next acquire from any thread, or the finalizer, finishes a doorway an exited thread left pending. An unparsable lock-path occupant raises once it stays unchanged for two seconds, a failed filesystem-clock probe trusts no age, and claims no longer probes. break_lock_file re-checks the marker right before renaming it. SoftReadWriteLock: gen/HEAD carries the epoch and only names a generation that must still read back, compaction unlinks oldest first so survivors stay contiguous, a commit refuses a successor whose predecessor is gone before and after its link, HEAD only moves forward, and a failed HEAD rename no longer fails a landed commit (#795, #799). HEAD, a hint readers verify, is no longer flushed, which halves the flushes per commit; a torn one counts as missing. The log and singleton key go back to 4.0.12's location (#801). Heartbeat and poll intervals are bounded by threading.TIMEOUT_MAX, and an interrupted release still leaves. BaseFileLock: cross-thread force releases take the transition lock, and a release a signal handler interrupts stays recoverable on every supported Python: the releasing flag names the releasing frame, the registry entry goes only while it is still ours, a retried release finishes a stale one, and Windows treats a second unlock as done (#810). A lease's claim travels with its hold (#791). Every lock validates timeouts, intervals and lifetime the same way, accepts Decimal and Fraction again, deprecates a string timeout in the setter, and compares singleton timeouts by the wait they mean (#803). filelock.version is the version string again (#790). A lock finalized at exit skips the fork bookkeeping a frozen daemon thread may hold, an acquire a signal handler starts mid-acquire raises instead of hanging, and a value too small for a float keeps its sign. asyncio: a re-entrant acquire skips path resolution, a finalizer falls back to a sync release when its scheduled one cannot run (#800), a finalized singleton leaves the cache first, and a finalized thread-local lock releases every thread's hold. Soft markers: a lease_duration float subclass is recorded as a plain float, a host-namespace contender keeps a marker whose owner still runs in another namespace under the recorded PID and start time, a Timeout names a holder it cannot probe, and a lease heartbeat rides out one missing refresh (#797, #786). SoftFileLock unlinks its marker before it relinquishes the descriptor, so an interrupted release can be retried; Windows finishes a pending unlink on the next acquire or release and takes and closes the pending descriptor in one C call chain. ReadWriteLock: probe releases never wait on the table lock and resume after an interrupt, a connect reuses an idle probe of its inode, and the async wrapper releases only its own level of a shared singleton (#794, #806). On macOS a connect beside a holder goes through a private hard link so SQLite reuses its deferred descriptors; link directories carry their owner in the name, and the first link beside a database removes those of dead processes. A connect lists its probe before leasing it, so an interrupt cannot pin the inode's probes. A fork transition finished on another thread clears the thread that entered it. Docs and changelog: every fragment states only the change since 4.0.12, and the contradictions the review listed are fixed.
gaborbernat
added a commit
that referenced
this pull request
Oct 9, 2026
A coherence review of the PRs merged since 4.0.12 found failures that come from those PRs or from how they interact; follow-up reviews found older gaps around interrupted releases and interpreter exit. StrictSoftFileLock: an EEXIST link counts as committed when the claim names the file behind the publisher's own descriptor, so a peer reaping the private record no longer orphans the intent (#787, #792). The next acquire from any thread, or the finalizer, finishes a doorway an exited thread left pending. An unparsable lock-path occupant raises once it stays unchanged for two seconds, a failed filesystem-clock probe trusts no age, and claims no longer probes. break_lock_file re-checks the marker right before renaming it. SoftReadWriteLock: gen/HEAD carries the epoch and only names a generation that must still read back, compaction unlinks oldest first so survivors stay contiguous, a commit refuses a successor whose predecessor is gone before and after its link, HEAD only moves forward, and a failed HEAD rename no longer fails a landed commit (#795, #799). HEAD, a hint readers verify, is no longer flushed, which halves the flushes per commit; a torn one counts as missing. The log and singleton key go back to 4.0.12's location (#801). Heartbeat and poll intervals are bounded by threading.TIMEOUT_MAX, and an interrupted release still leaves. BaseFileLock: cross-thread force releases take the transition lock, and a release a signal handler interrupts stays recoverable on every supported Python: the releasing flag names the releasing frame, the registry entry goes only while it is still ours, a retried release finishes a stale one, and Windows treats a second unlock as done (#810). A lease's claim travels with its hold (#791). Every lock validates timeouts, intervals and lifetime the same way, accepts Decimal and Fraction again, deprecates a string timeout in the setter, and compares singleton timeouts by the wait they mean (#803). filelock.version is the version string again (#790). A lock finalized at exit skips the fork bookkeeping a frozen daemon thread may hold, an acquire a signal handler starts mid-acquire raises instead of hanging, and a value too small for a float keeps its sign. asyncio: a re-entrant acquire skips path resolution, a finalizer falls back to a sync release when its scheduled one cannot run (#800), a finalized singleton leaves the cache first, and a finalized thread-local lock releases every thread's hold. Soft markers: a lease_duration float subclass is recorded as a plain float, a host-namespace contender keeps a marker whose owner still runs in another namespace under the recorded PID and start time, a Timeout names a holder it cannot probe, and a lease heartbeat rides out one missing refresh (#797, #786). SoftFileLock unlinks its marker before it relinquishes the descriptor, so an interrupted release can be retried; Windows finishes a pending unlink on the next acquire or release and takes and closes the pending descriptor in one C call chain. ReadWriteLock: probe releases never wait on the table lock and resume after an interrupt, a connect reuses an idle probe of its inode, and the async wrapper releases only its own level of a shared singleton (#794, #806). On macOS a connect beside a holder goes through a private hard link so SQLite reuses its deferred descriptors; link directories carry their owner in the name, and the first link beside a database removes those of dead processes. A connect lists its probe before leasing it, so an interrupt cannot pin the inode's probes. A fork transition finished on another thread clears the thread that entered it. Docs and changelog: every fragment states only the change since 4.0.12, and the contradictions the review listed are fixed.
gaborbernat
added a commit
that referenced
this pull request
Oct 9, 2026
A coherence review of the PRs merged since 4.0.12 found failures that come from those PRs or from how they interact; follow-up reviews found older gaps around interrupted releases and interpreter exit. StrictSoftFileLock: an EEXIST link counts as committed when the claim names the file behind the publisher's own descriptor, so a peer reaping the private record no longer orphans the intent (#787, #792). The next acquire from any thread, or the finalizer, finishes a doorway an exited thread left pending. An unparsable lock-path occupant raises once it stays unchanged for two seconds, a failed filesystem-clock probe trusts no age, and claims no longer probes. break_lock_file re-checks the marker right before renaming it. SoftReadWriteLock: gen/HEAD carries the epoch and only names a generation that must still read back, compaction unlinks oldest first so survivors stay contiguous, a commit refuses a successor whose predecessor is gone before and after its link, HEAD only moves forward, and a failed HEAD rename no longer fails a landed commit (#795, #799). HEAD, a hint readers verify, is no longer flushed, which halves the flushes per commit; a torn one counts as missing. The log and singleton key go back to 4.0.12's location (#801). Heartbeat and poll intervals are bounded by threading.TIMEOUT_MAX, and an interrupted release still leaves. BaseFileLock: cross-thread force releases take the transition lock, and a release a signal handler interrupts stays recoverable on every supported Python: the releasing flag names the releasing frame, the registry entry goes only while it is still ours, a retried release finishes a stale one, and Windows treats a second unlock as done (#810). A lease's claim travels with its hold (#791). Every lock validates timeouts, intervals and lifetime the same way, accepts Decimal and Fraction again, deprecates a string timeout in the setter, and compares singleton timeouts by the wait they mean (#803). filelock.version is the version string again (#790). A lock finalized at exit skips the fork bookkeeping a frozen daemon thread may hold, an acquire a signal handler starts mid-acquire raises instead of hanging, and a value too small for a float keeps its sign. asyncio: a re-entrant acquire skips path resolution, a finalizer falls back to a sync release when its scheduled one cannot run (#800), a finalized singleton leaves the cache first, and a finalized thread-local lock releases every thread's hold. Soft markers: a lease_duration float subclass is recorded as a plain float, a host-namespace contender keeps a marker whose owner still runs in another namespace under the recorded PID and start time, a Timeout names a holder it cannot probe, and a lease heartbeat rides out one missing refresh (#797, #786). SoftFileLock unlinks its marker before it relinquishes the descriptor, so an interrupted release can be retried; Windows finishes a pending unlink on the next acquire or release and takes and closes the pending descriptor in one C call chain. ReadWriteLock: probe releases never wait on the table lock and resume after an interrupt, a connect reuses an idle probe of its inode, and the async wrapper releases only its own level of a shared singleton (#794, #806). On macOS a connect beside a holder goes through a private hard link so SQLite reuses its deferred descriptors; link directories carry their owner in the name, and the first link beside a database removes those of dead processes. A connect lists its probe before leasing it, so an interrupt cannot pin the inode's probes. A fork transition finished on another thread clears the thread that entered it. Docs and changelog: every fragment states only the change since 4.0.12, and the contradictions the review listed are fixed.
gaborbernat
added a commit
that referenced
this pull request
Oct 9, 2026
A coherence review of the PRs merged since 4.0.12 found failures that come from those PRs or from how they interact; follow-up reviews found older gaps around interrupted releases and interpreter exit. StrictSoftFileLock: an EEXIST link counts as committed when the claim names the file behind the publisher's own descriptor, so a peer reaping the private record no longer orphans the intent (#787, #792). The next acquire from any thread, or the finalizer, finishes a doorway an exited thread left pending. An unparsable lock-path occupant raises once it stays unchanged for two seconds, a failed filesystem-clock probe trusts no age, and claims no longer probes. break_lock_file re-checks the marker right before renaming it. SoftReadWriteLock: gen/HEAD carries the epoch and only names a generation that must still read back, compaction unlinks oldest first so survivors stay contiguous, a commit refuses a successor whose predecessor is gone before and after its link, HEAD only moves forward, and a failed HEAD rename no longer fails a landed commit (#795, #799). HEAD, a hint readers verify, is no longer flushed, which halves the flushes per commit; a torn one counts as missing. The log and singleton key go back to 4.0.12's location (#801). Heartbeat and poll intervals are bounded by threading.TIMEOUT_MAX, and an interrupted release still leaves. BaseFileLock: cross-thread force releases take the transition lock, and a release a signal handler interrupts stays recoverable on every supported Python: the releasing flag names the releasing frame, the registry entry goes only while it is still ours, a retried release finishes a stale one, and Windows treats a second unlock as done (#810). A lease's claim travels with its hold (#791). Every lock validates timeouts, intervals and lifetime the same way, accepts Decimal and Fraction again, deprecates a string timeout in the setter, and compares singleton timeouts by the wait they mean (#803). filelock.version is the version string again (#790). A lock finalized at exit skips the fork bookkeeping a frozen daemon thread may hold, an acquire a signal handler starts mid-acquire raises instead of hanging, and a value too small for a float keeps its sign. asyncio: a re-entrant acquire skips path resolution, a finalizer falls back to a sync release when its scheduled one cannot run (#800), a finalized singleton leaves the cache first, and a finalized thread-local lock releases every thread's hold. Soft markers: a lease_duration float subclass is recorded as a plain float, a host-namespace contender keeps a marker whose owner still runs in another namespace under the recorded PID and start time, a Timeout names a holder it cannot probe, and a lease heartbeat rides out one missing refresh (#797, #786). SoftFileLock unlinks its marker before it relinquishes the descriptor, so an interrupted release can be retried; Windows finishes a pending unlink on the next acquire or release and takes and closes the pending descriptor in one C call chain. ReadWriteLock: probe releases never wait on the table lock and resume after an interrupt, a connect reuses an idle probe of its inode, and the async wrapper releases only its own level of a shared singleton (#794, #806). On macOS a connect beside a holder goes through a private hard link so SQLite reuses its deferred descriptors; link directories carry their owner in the name, and the first link beside a database removes those of dead processes. A connect lists its probe before leasing it, so an interrupt cannot pin the inode's probes. A fork transition finished on another thread clears the thread that entered it. Docs and changelog: every fragment states only the change since 4.0.12, and the contradictions the review listed are fixed.
parthea
pushed a commit
to googleapis/google-cloud-python
that referenced
this pull request
Oct 13, 2026
This PR contains the following updates: | Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) | |---|---|---|---| | [filelock](https://redirect.github.com/tox-dev/py-filelock) | `==3.29.0` → `==4.1.1` |  |  | --- ### Release Notes <details> <summary>tox-dev/py-filelock (filelock)</summary> ### [`v4.1.1`](https://redirect.github.com/tox-dev/filelock/releases/tag/4.1.1) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/4.1.0...4.1.1) <!-- Release notes generated using configuration in .github/release.yaml at 4.1.1 --> #### What's Changed - feat(python): default to Python 3.15 by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#816](https://redirect.github.com/tox-dev/filelock/pull/816) - fix(rw): avoid macOS descriptor lookups by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#820](https://redirect.github.com/tox-dev/filelock/pull/820) - fix(tests): bound concurrent lock progress by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#819](https://redirect.github.com/tox-dev/filelock/pull/819) - test: make lock error checks deterministic by [@​adenzhou1350](https://redirect.github.com/adenzhou1350) in [tox-dev/filelock#817](https://redirect.github.com/tox-dev/filelock/pull/817) - fix(read-write): reject a hostile pid in \_owner_is_gone by [@​dxbjavid](https://redirect.github.com/dxbjavid) in [tox-dev/filelock#821](https://redirect.github.com/tox-dev/filelock/pull/821) #### New Contributors - [@​adenzhou1350](https://redirect.github.com/adenzhou1350) made their first contribution in [tox-dev/filelock#817](https://redirect.github.com/tox-dev/filelock/pull/817) **Full Changelog**: <https://github.com/tox-dev/filelock/compare/4.1.0...4.1.1> ### [`v4.1.0`](https://redirect.github.com/tox-dev/filelock/releases/tag/4.1.0) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/4.0.12...4.1.0) <!-- Release notes generated using configuration in .github/release.yaml at 4.1.0 --> #### What's Changed - ci: download coverage during tool setup by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#776](https://redirect.github.com/tox-dev/filelock/pull/776) - 🐛 fix(api): validate timeout and poll_interval bounds by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#781](https://redirect.github.com/tox-dev/filelock/pull/781) - 🐛 fix(read-write): accept inf and reject nan timeouts by [@​darrenhuai](https://redirect.github.com/darrenhuai) in [tox-dev/filelock#779](https://redirect.github.com/tox-dev/filelock/pull/779) - 🐛 fix(soft-rw): ignore non-ASCII generation names by [@​dxbjavid](https://redirect.github.com/dxbjavid) in [tox-dev/filelock#778](https://redirect.github.com/tox-dev/filelock/pull/778) - 🐛 fix(soft): check start token in is_lock_held_by_us by [@​lprnmns](https://redirect.github.com/lprnmns) in [tox-dev/filelock#774](https://redirect.github.com/tox-dev/filelock/pull/774) - 🐛 fix(soft): clean up marker when rollback close fails by [@​harbinresearcher](https://redirect.github.com/harbinresearcher) in [tox-dev/filelock#775](https://redirect.github.com/tox-dev/filelock/pull/775) - 🐛 fix(read-write): clamp waits to threading.TIMEOUT_MAX by [@​darrenhuai](https://redirect.github.com/darrenhuai) in [tox-dev/filelock#780](https://redirect.github.com/tox-dev/filelock/pull/780) - 🐛 fix(soft): treat truncated markers as malformed by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#782](https://redirect.github.com/tox-dev/filelock/pull/782) - 🐛 fix(acquire): keep every acquire wait within the timeout by [@​feiiiiii5](https://redirect.github.com/feiiiiii5) in [tox-dev/filelock#777](https://redirect.github.com/tox-dev/filelock/pull/777) - 📝 docs: fix hanging example and platform claims by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#783](https://redirect.github.com/tox-dev/filelock/pull/783) - 🐛 fix(unix): keep peer marker on ENOSYS fallback by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#785](https://redirect.github.com/tox-dev/filelock/pull/785) - 🐛 fix(async): clear the task hold after a canceled release by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#789](https://redirect.github.com/tox-dev/filelock/pull/789) - ✨ feat(api): export lease types and has_fcntl by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#790](https://redirect.github.com/tox-dev/filelock/pull/790) - 🐛 fix(strict): age private records by the filesystem clock by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#792](https://redirect.github.com/tox-dev/filelock/pull/792) - 🐛 fix(async): surface executor shutdown as an error by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#793](https://redirect.github.com/tox-dev/filelock/pull/793) - 🐛 fix(soft): expire leases on the contender's clock by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#796](https://redirect.github.com/tox-dev/filelock/pull/796) - 🐛 fix(soft-rw): stop an acquire that close() overtook by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#798](https://redirect.github.com/tox-dev/filelock/pull/798) - 🐛 fix(strict): record claims before linking them by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#787](https://redirect.github.com/tox-dev/filelock/pull/787) - 🐛 fix(soft): restore a live marker a stale break moved aside by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#786](https://redirect.github.com/tox-dev/filelock/pull/786) - 🐛 fix(api): chain errors on 3.10 without exceptiongroup by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#788](https://redirect.github.com/tox-dev/filelock/pull/788) - 🐛 fix(soft): release a dropped SoftFileLease by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#791](https://redirect.github.com/tox-dev/filelock/pull/791) - 🐛 fix(read-write): keep probe fds until the last connection closes by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#794](https://redirect.github.com/tox-dev/filelock/pull/794) - 📦 build(sdist): ship docs and update SECURITY.md by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#812](https://redirect.github.com/tox-dev/filelock/pull/812) - 🐛 fix(soft-rw): survive a removed generation log by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#795](https://redirect.github.com/tox-dev/filelock/pull/795) - 🐛 fix(soft): tell PID namespaces apart in the marker host by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#797](https://redirect.github.com/tox-dev/filelock/pull/797) - 🐛 fix(async): release from the finalizer and keep I/O off the loop by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#800](https://redirect.github.com/tox-dev/filelock/pull/800) - 🐛 fix(strict): name what blocks the lock path by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#804](https://redirect.github.com/tox-dev/filelock/pull/804) - 🐛 fix(read-write): reject WAL databases and link beside the db by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#805](https://redirect.github.com/tox-dev/filelock/pull/805) - 🐛 fix(read-write): track read depth per thread by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#806](https://redirect.github.com/tox-dev/filelock/pull/806) - 🐛 fix(soft): honour mode and tighten marker grammar by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#807](https://redirect.github.com/tox-dev/filelock/pull/807) - 🧪 test: drop timing races from two runner-load flakes by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#809](https://redirect.github.com/tox-dev/filelock/pull/809) - 🐛 fix(descriptor): reject poll intervals above TIMEOUT_MAX by [@​sricharanreddycheruku](https://redirect.github.com/sricharanreddycheruku) in [tox-dev/filelock#802](https://redirect.github.com/tox-dev/filelock/pull/802) - 🐛 fix(api): validate lock options up front by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#803](https://redirect.github.com/tox-dev/filelock/pull/803) - 🐛 fix(soft-rw): publish the head through gen/HEAD by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#799](https://redirect.github.com/tox-dev/filelock/pull/799) - 🐛 fix(api): release thread holds, guard reentry by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#810](https://redirect.github.com/tox-dev/filelock/pull/810) - 🧪 test(lease): give the age-out test a real-time margin by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#814](https://redirect.github.com/tox-dev/filelock/pull/814) - 📝 docs: point canonical and og:url at versioned pages by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#813](https://redirect.github.com/tox-dev/filelock/pull/813) - 🐛 fix(read-write): refuse a database moved mid-acquire by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#808](https://redirect.github.com/tox-dev/filelock/pull/808) - 🐛 fix: close regressions since 4.0.12 by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#815](https://redirect.github.com/tox-dev/filelock/pull/815) #### New Contributors - [@​darrenhuai](https://redirect.github.com/darrenhuai) made their first contribution in [tox-dev/filelock#779](https://redirect.github.com/tox-dev/filelock/pull/779) - [@​harbinresearcher](https://redirect.github.com/harbinresearcher) made their first contribution in [tox-dev/filelock#775](https://redirect.github.com/tox-dev/filelock/pull/775) - [@​sricharanreddycheruku](https://redirect.github.com/sricharanreddycheruku) made their first contribution in [tox-dev/filelock#802](https://redirect.github.com/tox-dev/filelock/pull/802) **Full Changelog**: <https://github.com/tox-dev/filelock/compare/4.0.12...4.1.0> ### [`v4.0.12`](https://redirect.github.com/tox-dev/filelock/releases/tag/4.0.12) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/4.0.11...4.0.12) <!-- Release notes generated using configuration in .github/release.yaml at 4.0.12 --> #### What's Changed - fix: support older SQLite read locks by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#771](https://redirect.github.com/tox-dev/filelock/pull/771) **Full Changelog**: <https://github.com/tox-dev/filelock/compare/4.0.11...4.0.12> ### [`v4.0.11`](https://redirect.github.com/tox-dev/filelock/releases/tag/4.0.11) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/4.0.10...4.0.11) <!-- Release notes generated using configuration in .github/release.yaml at 4.0.11 --> #### What's Changed - docs: select an existing tox environment in contributing guide by [@​raghav-sharma-ai](https://redirect.github.com/raghav-sharma-ai) in [tox-dev/filelock#767](https://redirect.github.com/tox-dev/filelock/pull/767) - fix(read-write): handle NetBSD fd limits by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#768](https://redirect.github.com/tox-dev/filelock/pull/768) #### New Contributors - [@​raghav-sharma-ai](https://redirect.github.com/raghav-sharma-ai) made their first contribution in [tox-dev/filelock#767](https://redirect.github.com/tox-dev/filelock/pull/767) **Full Changelog**: <https://github.com/tox-dev/filelock/compare/4.0.10...4.0.11> ### [`v4.0.10`](https://redirect.github.com/tox-dev/filelock/releases/tag/4.0.10) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/4.0.9...4.0.10) <!-- Release notes generated using configuration in .github/release.yaml at 4.0.10 --> #### What's Changed - ♻️ refactor(util): test helpers via public locks by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#764](https://redirect.github.com/tox-dev/filelock/pull/764) - 🐛 fix(singleton): reject conflicting async and lease options by [@​kokotatan](https://redirect.github.com/kokotatan) in [tox-dev/filelock#765](https://redirect.github.com/tox-dev/filelock/pull/765) #### New Contributors - [@​kokotatan](https://redirect.github.com/kokotatan) made their first contribution in [tox-dev/filelock#765](https://redirect.github.com/tox-dev/filelock/pull/765) **Full Changelog**: <https://github.com/tox-dev/filelock/compare/4.0.9...4.0.10> ### [`v4.0.9`](https://redirect.github.com/tox-dev/filelock/releases/tag/4.0.9) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/4.0.8...4.0.9) <!-- Release notes generated using configuration in .github/release.yaml at 4.0.9 --> #### What's Changed - 📝 docs(util): correct write and break guarantees by [@​pralav-25](https://redirect.github.com/pralav-25) in [tox-dev/filelock#762](https://redirect.github.com/tox-dev/filelock/pull/762) - 🐛 fix(read-write): close db fd after connect by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#763](https://redirect.github.com/tox-dev/filelock/pull/763) #### New Contributors - [@​pralav-25](https://redirect.github.com/pralav-25) made their first contribution in [tox-dev/filelock#762](https://redirect.github.com/tox-dev/filelock/pull/762) **Full Changelog**: <https://github.com/tox-dev/filelock/compare/4.0.8...4.0.9> ### [`v4.0.8`](https://redirect.github.com/tox-dev/filelock/releases/tag/4.0.8) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/4.0.7...4.0.8) <!-- Release notes generated using configuration in .github/release.yaml at 4.0.8 --> #### What's Changed - 🐛 fix(read-write): refuse cross-thread write release by [@​feiiiiii5](https://redirect.github.com/feiiiiii5) in [tox-dev/filelock#761](https://redirect.github.com/tox-dev/filelock/pull/761) **Full Changelog**: <https://github.com/tox-dev/filelock/compare/4.0.7...4.0.8> ### [`v4.0.7`](https://redirect.github.com/tox-dev/filelock/releases/tag/4.0.7) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/4.0.6...4.0.7) <!-- Release notes generated using configuration in .github/release.yaml at 4.0.7 --> #### What's Changed - 🐛 fix(mode): require owner read and write by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#760](https://redirect.github.com/tox-dev/filelock/pull/760) **Full Changelog**: <https://github.com/tox-dev/filelock/compare/4.0.6...4.0.7> ### [`v4.0.6`](https://redirect.github.com/tox-dev/filelock/releases/tag/4.0.6) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/4.0.5...4.0.6) <!-- Release notes generated using configuration in .github/release.yaml at 4.0.6 --> #### What's Changed - fix(read-write): validate reentrant timeouts by [@​feiiiiii5](https://redirect.github.com/feiiiiii5) in [tox-dev/filelock#756](https://redirect.github.com/tox-dev/filelock/pull/756) **Full Changelog**: <https://github.com/tox-dev/filelock/compare/4.0.5...4.0.6> ### [`v4.0.5`](https://redirect.github.com/tox-dev/filelock/releases/tag/4.0.5) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/4.0.4...4.0.5) <!-- Release notes generated using configuration in .github/release.yaml at 4.0.5 --> #### What's Changed - fix(marker): preserve live owners by [@​DawnofGenX](https://redirect.github.com/DawnofGenX) in [tox-dev/filelock#751](https://redirect.github.com/tox-dev/filelock/pull/751) - fix(tests): separate mode and access checks by [@​pasmud](https://redirect.github.com/pasmud) in [tox-dev/filelock#753](https://redirect.github.com/tox-dev/filelock/pull/753) - fix(read-write): honor instance defaults by [@​DawnofGenX](https://redirect.github.com/DawnofGenX) in [tox-dev/filelock#752](https://redirect.github.com/tox-dev/filelock/pull/752) - fix(async): validate blocking read-write timeouts by [@​pasmud](https://redirect.github.com/pasmud) in [tox-dev/filelock#755](https://redirect.github.com/tox-dev/filelock/pull/755) - fix(strict): handle vanished unreadable claims by [@​januththedev](https://redirect.github.com/januththedev) in [tox-dev/filelock#754](https://redirect.github.com/tox-dev/filelock/pull/754) #### New Contributors - [@​DawnofGenX](https://redirect.github.com/DawnofGenX) made their first contribution in [tox-dev/filelock#751](https://redirect.github.com/tox-dev/filelock/pull/751) - [@​pasmud](https://redirect.github.com/pasmud) made their first contribution in [tox-dev/filelock#753](https://redirect.github.com/tox-dev/filelock/pull/753) - [@​januththedev](https://redirect.github.com/januththedev) made their first contribution in [tox-dev/filelock#754](https://redirect.github.com/tox-dev/filelock/pull/754) **Full Changelog**: <https://github.com/tox-dev/filelock/compare/4.0.4...4.0.5> ### [`v4.0.4`](https://redirect.github.com/tox-dev/filelock/releases/tag/4.0.4) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/4.0.3...4.0.4) <!-- Release notes generated using configuration in .github/release.yaml at 4.0.4 --> #### What's Changed - 🐛 fix(identity): digest the cut tail of long hostnames by [@​feiiiiii5](https://redirect.github.com/feiiiiii5) in [tox-dev/filelock#748](https://redirect.github.com/tox-dev/filelock/pull/748) #### New Contributors - [@​feiiiiii5](https://redirect.github.com/feiiiiii5) made their first contribution in [tox-dev/filelock#748](https://redirect.github.com/tox-dev/filelock/pull/748) **Full Changelog**: <https://github.com/tox-dev/filelock/compare/4.0.3...4.0.4> ### [`v4.0.3`](https://redirect.github.com/tox-dev/filelock/releases/tag/4.0.3) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/4.0.2...4.0.3) <!-- Release notes generated using configuration in .github/release.yaml at 4.0.3 --> #### What's Changed - 🐛 fix(api): skip the fork audit hook on CPython <3.12 by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#747](https://redirect.github.com/tox-dev/filelock/pull/747) **Full Changelog**: <https://github.com/tox-dev/filelock/compare/4.0.2...4.0.3> ### [`v4.0.2`](https://redirect.github.com/tox-dev/filelock/releases/tag/4.0.2) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/4.0.1...4.0.2) <!-- Release notes generated using configuration in .github/release.yaml at 4.0.2 --> #### What's Changed - docs: create the data directory in the async cache example by [@​agammann](https://redirect.github.com/agammann) in [tox-dev/filelock#740](https://redirect.github.com/tox-dev/filelock/pull/740) - fix: ignore broken sphinx-llm release by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#742](https://redirect.github.com/tox-dev/filelock/pull/742) - 🐛 fix(api): serialize concurrent transitions on shared locks by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#745](https://redirect.github.com/tox-dev/filelock/pull/745) - 🐛 fix(async-rw): give each task its own hold by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#746](https://redirect.github.com/tox-dev/filelock/pull/746) #### New Contributors - [@​agammann](https://redirect.github.com/agammann) made their first contribution in [tox-dev/filelock#740](https://redirect.github.com/tox-dev/filelock/pull/740) **Full Changelog**: <https://github.com/tox-dev/filelock/compare/4.0.1...4.0.2> ### [`v4.0.1`](https://redirect.github.com/tox-dev/filelock/releases/tag/4.0.1) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/4.0.0...4.0.1) <!-- Release notes generated using configuration in .github/release.yaml at 4.0.1 --> #### What's Changed - fix: reject invalid poll_interval before sleep by [@​Pitchfork-and-Torch](https://redirect.github.com/Pitchfork-and-Torch) in [tox-dev/filelock#739](https://redirect.github.com/tox-dev/filelock/pull/739) #### New Contributors - [@​Pitchfork-and-Torch](https://redirect.github.com/Pitchfork-and-Torch) made their first contribution in [tox-dev/filelock#739](https://redirect.github.com/tox-dev/filelock/pull/739) **Full Changelog**: <https://github.com/tox-dev/filelock/compare/4.0.0...4.0.1> ### [`v4.0.0`](https://redirect.github.com/tox-dev/filelock/releases/tag/4.0.0) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/3.32.7...4.0.0) <!-- Release notes generated using configuration in .github/release.yaml at 4.0.0 --> #### What's Changed - 🐛 fix(soft-rw): replace the state mutex with a generation log by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#738](https://redirect.github.com/tox-dev/filelock/pull/738) **Full Changelog**: <https://github.com/tox-dev/filelock/compare/3.32.7...4.0.0> ### [`v3.32.7`](https://redirect.github.com/tox-dev/filelock/releases/tag/3.32.7) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/3.32.6...3.32.7) <!-- Release notes generated using configuration in .github/release.yaml at 3.32.7 --> #### What's Changed - Fix final symlink test on musl by [@​lprnmns](https://redirect.github.com/lprnmns) in [tox-dev/filelock#737](https://redirect.github.com/tox-dev/filelock/pull/737) - 📝 docs: say acquire() falls back to the lock's blocking attribute by [@​hxperl](https://redirect.github.com/hxperl) in [tox-dev/filelock#733](https://redirect.github.com/tox-dev/filelock/pull/733) #### New Contributors - [@​hxperl](https://redirect.github.com/hxperl) made their first contribution in [tox-dev/filelock#733](https://redirect.github.com/tox-dev/filelock/pull/733) **Full Changelog**: <https://github.com/tox-dev/filelock/compare/3.32.6...3.32.7> ### [`v3.32.6`](https://redirect.github.com/tox-dev/filelock/releases/tag/3.32.6) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/3.32.5...3.32.6) <!-- Release notes generated using configuration in .github/release.yaml at 3.32.6 --> #### What's Changed - 🐛 fix(lease): reject a duration no marker can carry by [@​lprnmns](https://redirect.github.com/lprnmns) in [tox-dev/filelock#723](https://redirect.github.com/tox-dev/filelock/pull/723) - 🐛 fix(soft-rw): reject non-finite timing options by [@​lprnmns](https://redirect.github.com/lprnmns) in [tox-dev/filelock#724](https://redirect.github.com/tox-dev/filelock/pull/724) - fix: preserve exception notes when copying and pickling by [@​jackwalkerlabs](https://redirect.github.com/jackwalkerlabs) in [tox-dev/filelock#729](https://redirect.github.com/tox-dev/filelock/pull/729) - test(soft-rw): reuse existing test module by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#730](https://redirect.github.com/tox-dev/filelock/pull/730) - fix: respect ACL write access when the owner write bit is absent by [@​jackwalkerlabs](https://redirect.github.com/jackwalkerlabs) in [tox-dev/filelock#728](https://redirect.github.com/tox-dev/filelock/pull/728) - Fix SoftReadWriteLock state lock timeout by [@​Sohel2309](https://redirect.github.com/Sohel2309) in [tox-dev/filelock#726](https://redirect.github.com/tox-dev/filelock/pull/726) #### New Contributors - [@​jackwalkerlabs](https://redirect.github.com/jackwalkerlabs) made their first contribution in [tox-dev/filelock#729](https://redirect.github.com/tox-dev/filelock/pull/729) - [@​Sohel2309](https://redirect.github.com/Sohel2309) made their first contribution in [tox-dev/filelock#726](https://redirect.github.com/tox-dev/filelock/pull/726) **Full Changelog**: <https://github.com/tox-dev/filelock/compare/3.32.5...3.32.6> ### [`v3.32.5`](https://redirect.github.com/tox-dev/filelock/releases/tag/3.32.5) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/3.32.4...3.32.5) <!-- Release notes generated using configuration in .github/release.yaml at 3.32.5 --> #### What's Changed - 🧪 test(fork): report where a stalled fork stops by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#715](https://redirect.github.com/tox-dev/filelock/pull/715) - 📝 docs: say that mode is read-only in the thread-local section by [@​Gares95](https://redirect.github.com/Gares95) in [tox-dev/filelock#716](https://redirect.github.com/tox-dev/filelock/pull/716) - 🐛 fix(lease): clear token after failed acquire by [@​lprnmns](https://redirect.github.com/lprnmns) in [tox-dev/filelock#721](https://redirect.github.com/tox-dev/filelock/pull/721) #### New Contributors - [@​lprnmns](https://redirect.github.com/lprnmns) made their first contribution in [tox-dev/filelock#721](https://redirect.github.com/tox-dev/filelock/pull/721) **Full Changelog**: <https://github.com/tox-dev/filelock/compare/3.32.4...3.32.5> ### [`v3.32.4`](https://redirect.github.com/tox-dev/filelock/releases/tag/3.32.4) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/3.32.3...3.32.4) <!-- Release notes generated using configuration in .github/release.yaml at 3.32.4 --> #### What's Changed - 🐛 fix: retry transient denials on open and claim read by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#705](https://redirect.github.com/tox-dev/filelock/pull/705) - 🧪 test: deflake six scheduled-run failures by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#704](https://redirect.github.com/tox-dev/filelock/pull/704) - 🧪 test: cover a reclaimed private record for real by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#706](https://redirect.github.com/tox-dev/filelock/pull/706) - 🧪 test(fork): fork once the event loop has closed by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#714](https://redirect.github.com/tox-dev/filelock/pull/714) - 🔧 chore: batch dependency updates weekly on Tuesday by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#713](https://redirect.github.com/tox-dev/filelock/pull/713) - escape the hostname every marker publishes by [@​dxbjavid](https://redirect.github.com/dxbjavid) in [tox-dev/filelock#709](https://redirect.github.com/tox-dev/filelock/pull/709) **Full Changelog**: <https://github.com/tox-dev/filelock/compare/3.32.3...3.32.4> ### [`v3.32.3`](https://redirect.github.com/tox-dev/filelock/releases/tag/3.32.3) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/3.32.2...3.32.3) <!-- Release notes generated using configuration in .github/release.yaml at 3.32.3 --> #### What's Changed - 🧪 test(strict): deflake close-fault injections on graalpy by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#697](https://redirect.github.com/tox-dev/filelock/pull/697) - 📄 docs: publish llms.txt from the docs build by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#700](https://redirect.github.com/tox-dev/filelock/pull/700) - 🐛 fix(fork): survive audit events during interpreter shutdown by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#703](https://redirect.github.com/tox-dev/filelock/pull/703) **Full Changelog**: <https://github.com/tox-dev/filelock/compare/3.32.2...3.32.3> ### [`v3.32.2`](https://redirect.github.com/tox-dev/filelock/releases/tag/3.32.2) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/3.32.0...3.32.2) <!-- Release notes generated using configuration in .github/release.yaml at 3.32.2 --> #### What's Changed - Fix test failures on NetBSD ([#​689](https://redirect.github.com/tox-dev/py-filelock/issues/689)) by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#693](https://redirect.github.com/tox-dev/filelock/pull/693) - 🧪 test(soft-rw): deflake writer phase-2 peer-marker test by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#694](https://redirect.github.com/tox-dev/filelock/pull/694) - hand back the claim when a heartbeat thread fails to start by [@​dxbjavid](https://redirect.github.com/dxbjavid) in [tox-dev/filelock#691](https://redirect.github.com/tox-dev/filelock/pull/691) - 🧪 test(unix): deflake sticky-bit concurrent-unlink on graalpy by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#695](https://redirect.github.com/tox-dev/filelock/pull/695) **Full Changelog**: <https://github.com/tox-dev/filelock/compare/3.32.1...3.32.2> ### [`v3.32.0`](https://redirect.github.com/tox-dev/filelock/releases/tag/3.32.0) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/3.31.2...3.32.0) <!-- Release notes generated using configuration in .github/release.yaml at 3.32.0 --> #### What's Changed - 👷 ci: add Python 3.15 to the test matrix by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#683](https://redirect.github.com/tox-dev/filelock/pull/683) - 🐛 fix(packaging): let an unpacked sdist run the test suite by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#685](https://redirect.github.com/tox-dev/filelock/pull/685) **Full Changelog**: <https://github.com/tox-dev/filelock/compare/3.31.2...3.32.0> ### [`v3.31.2`](https://redirect.github.com/tox-dev/filelock/releases/tag/3.31.2) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/3.31.1...3.31.2) <!-- Release notes generated using configuration in .github/release.yaml at 3.31.2 --> #### What's Changed - 🐛 fix(strict): tolerate an errno without ENOTSUP by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#681](https://redirect.github.com/tox-dev/filelock/pull/681) **Full Changelog**: <https://github.com/tox-dev/filelock/compare/3.31.1...3.31.2> ### [`v3.31.1`](https://redirect.github.com/tox-dev/filelock/releases/tag/3.31.1) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/3.31.0...3.31.1) <!-- Release notes generated using configuration in .github/release.yaml at 3.31.1 --> #### What's Changed - ♻️ refactor(coverage): key exclusions on probed capability by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#679](https://redirect.github.com/tox-dev/filelock/pull/679) - scope a lease's claim to the context that acquired it by [@​dxbjavid](https://redirect.github.com/dxbjavid) in [tox-dev/filelock#680](https://redirect.github.com/tox-dev/filelock/pull/680) **Full Changelog**: <https://github.com/tox-dev/filelock/compare/3.31.0...3.31.1> ### [`v3.31.0`](https://redirect.github.com/tox-dev/filelock/releases/tag/3.31.0) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/3.30.3...3.31.0) <!-- Release notes generated using configuration in .github/release.yaml at 3.31.0 --> #### What's Changed - ✨ feat(platform): support Termux/Android by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#678](https://redirect.github.com/tox-dev/filelock/pull/678) **Full Changelog**: <https://github.com/tox-dev/filelock/compare/3.30.3...3.31.0> ### [`v3.30.3`](https://redirect.github.com/tox-dev/filelock/releases/tag/3.30.3) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/3.30.2...3.30.3) <!-- Release notes generated using configuration in .github/release.yaml at 3.30.3 --> #### What's Changed - Keep both tables of contents on screen at any browser font size by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#673](https://redirect.github.com/tox-dev/filelock/pull/673) - 📝 docs(mermaid): follow the light and dark theme toggle by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#674](https://redirect.github.com/tox-dev/filelock/pull/674) - asyncio: scope the reentrant-deadlock registry to the owning task by [@​xt-yin](https://redirect.github.com/xt-yin) in [tox-dev/filelock#676](https://redirect.github.com/tox-dev/filelock/pull/676) #### New Contributors - [@​xt-yin](https://redirect.github.com/xt-yin) made their first contribution in [tox-dev/filelock#676](https://redirect.github.com/tox-dev/filelock/pull/676) **Full Changelog**: <https://github.com/tox-dev/filelock/compare/3.30.2...3.30.3> ### [`v3.30.2`](https://redirect.github.com/tox-dev/filelock/releases/tag/3.30.2) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/3.30.1...3.30.2) <!-- Release notes generated using configuration in .github/release.yaml at 3.30.2 --> #### What's Changed - Document every lock type, and stop evicting a marker we cannot read by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#672](https://redirect.github.com/tox-dev/filelock/pull/672) **Full Changelog**: <https://github.com/tox-dev/filelock/compare/3.30.1...3.30.2> ### [`v3.30.1`](https://redirect.github.com/tox-dev/filelock/releases/tag/3.30.1) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/3.30.0...3.30.1) <!-- Release notes generated using configuration in .github/release.yaml at 3.30.1 --> #### What's Changed - 📝 docs: separate changelog releases with a blank line by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#668](https://redirect.github.com/tox-dev/filelock/pull/668) - 🐛 fix: tolerate NFSv3 stale handle in strict claim read by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#669](https://redirect.github.com/tox-dev/filelock/pull/669) - Match fork-reset protocol on the class object by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#671](https://redirect.github.com/tox-dev/filelock/pull/671) - reject non-finite lease duration in marker records by [@​dxbjavid](https://redirect.github.com/dxbjavid) in [tox-dev/filelock#670](https://redirect.github.com/tox-dev/filelock/pull/670) **Full Changelog**: <https://github.com/tox-dev/filelock/compare/3.30.0...3.30.1> ### [`v3.30.0`](https://redirect.github.com/tox-dev/filelock/releases/tag/3.30.0) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/3.29.7...3.30.0) <!-- Release notes generated using configuration in .github/release.yaml at 3.30.0 --> #### What's Changed - 🎨 style: readability cleanup across the library by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#598](https://redirect.github.com/tox-dev/filelock/pull/598) - 🐛 fix(api): ignore lifetime on native OS locks by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#593](https://redirect.github.com/tox-dev/filelock/pull/593) - 🐛 fix(unix): don't mutate lock file before acquiring flock by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#594](https://redirect.github.com/tox-dev/filelock/pull/594) - soft: evict a non-regular lock file without reading it by [@​dxbjavid](https://redirect.github.com/dxbjavid) in [tox-dev/filelock#597](https://redirect.github.com/tox-dev/filelock/pull/597) - 🐛 fix(windows): bind reparse-point check to the locked handle by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#596](https://redirect.github.com/tox-dev/filelock/pull/596) - 🐛 fix(api): make native lock release transactional by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#615](https://redirect.github.com/tox-dev/filelock/pull/615) - 🐛 fix(soft): make marker writes and cleanup transactional by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#614](https://redirect.github.com/tox-dev/filelock/pull/614) - 🐛 fix(windows): open the lock file through NtCreateFile by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#617](https://redirect.github.com/tox-dev/filelock/pull/617) - ✨ feat(api): add context_error_policy for dual context failures by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#618](https://redirect.github.com/tox-dev/filelock/pull/618) - 📝 docs: correct Unix lock-file cleanup and flock claims by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#623](https://redirect.github.com/tox-dev/filelock/pull/623) - ✨ feat(api): add close_error_policy for post-unlock close errors by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#619](https://redirect.github.com/tox-dev/filelock/pull/619) - 🐛 fix(api): canonicalize singleton keys without following a final symlink by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#621](https://redirect.github.com/tox-dev/filelock/pull/621) - ✨ feat(unix): add fallback_to_soft opt-out for native locks by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#622](https://redirect.github.com/tox-dev/filelock/pull/622) - ✨ feat: add lock_descriptor for a caller-owned descriptor by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#620](https://redirect.github.com/tox-dev/filelock/pull/620) - ✨ feat(api): add preserve_lock_file to keep the lock pathname by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#624](https://redirect.github.com/tox-dev/filelock/pull/624) - ✨ feat(api): add on_acquired post-acquisition hook by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#625](https://redirect.github.com/tox-dev/filelock/pull/625) - 🔧 build(release): towncrier changelog pipeline, backfill, and docs by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#626](https://redirect.github.com/tox-dev/filelock/pull/626) - 📝 docs: drop bot entries and link code refs in the changelog by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#638](https://redirect.github.com/tox-dev/filelock/pull/638) - 🐛 fix(api): validate lifetime values by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#644](https://redirect.github.com/tox-dev/filelock/pull/644) - 🐛 fix(win32): capture process probe errors by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#645](https://redirect.github.com/tox-dev/filelock/pull/645) - 🐛 fix(api): reject dropped lock options by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#646](https://redirect.github.com/tox-dev/filelock/pull/646) - 🐛 fix(api): retain acquisition path identity by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#647](https://redirect.github.com/tox-dev/filelock/pull/647) - 🐛 fix(api): detach grouped release errors by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#648](https://redirect.github.com/tox-dev/filelock/pull/648) - 🐛 fix(descriptor): define unavailable behavior by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#650](https://redirect.github.com/tox-dev/filelock/pull/650) - 🐛 fix(ci): map absolute coverage paths by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#651](https://redirect.github.com/tox-dev/filelock/pull/651) - 🐛 fix(soft): relinquish fd before close by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#649](https://redirect.github.com/tox-dev/filelock/pull/649) - 🐛 fix(async): make cancellation atomic by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#652](https://redirect.github.com/tox-dev/filelock/pull/652) - 🐛 fix(sqlite): isolate forked connections by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#657](https://redirect.github.com/tox-dev/filelock/pull/657) - 🧪 test(conftest): scope the close mock to one descriptor by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#656](https://redirect.github.com/tox-dev/filelock/pull/656) - ✨ feat(soft): add strict soft locks and leases by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#658](https://redirect.github.com/tox-dev/filelock/pull/658) - ✨ feat(strict): replace shared markers with owner claims by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#659](https://redirect.github.com/tox-dev/filelock/pull/659) - 🐛 fix(soft): detect a reused PID via process start time by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#660](https://redirect.github.com/tox-dev/filelock/pull/660) - 🔒 fix(soft): fail safe on transient heartbeat errors by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#661](https://redirect.github.com/tox-dev/filelock/pull/661) - 📝 docs: state the lock trust boundaries once by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#663](https://redirect.github.com/tox-dev/filelock/pull/663) - 👷 ci(perf): add the performance and NFS matrix by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#664](https://redirect.github.com/tox-dev/filelock/pull/664) - Replace prettier with mdformat and yamlfmt by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#667](https://redirect.github.com/tox-dev/filelock/pull/667) - 👷 ci(matrix): add SMB, capability, and matrix docs by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#665](https://redirect.github.com/tox-dev/filelock/pull/665) **Full Changelog**: <https://github.com/tox-dev/filelock/compare/3.29.7...3.30.0> ### [`v3.29.7`](https://redirect.github.com/tox-dev/filelock/releases/tag/3.29.7) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/3.29.6...3.29.7) <!-- Release notes generated using configuration in .github/release.yaml at main --> #### What's Changed - asyncio: detect cross-instance reentrant deadlocks before the poll loop by [@​HrachShah](https://redirect.github.com/HrachShah) in [tox-dev/filelock#586](https://redirect.github.com/tox-dev/filelock/pull/586) - 🐛 fix(soft_rw): evict non-regular write marker without reading it by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#588](https://redirect.github.com/tox-dev/filelock/pull/588) - \_util: drop the dead st_mtime=0 short-circuit in raise_on_not_writable_file by [@​HrachShah](https://redirect.github.com/HrachShah) in [tox-dev/filelock#589](https://redirect.github.com/tox-dev/filelock/pull/589) **Full Changelog**: <https://github.com/tox-dev/filelock/compare/3.29.6...3.29.7> ### [`v3.29.6`](https://redirect.github.com/tox-dev/filelock/releases/tag/3.29.6) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/3.29.5...3.29.6) <!-- Release notes generated using configuration in .github/release.yaml at main --> #### What's Changed - serialise singleton construction in FileLockMeta by [@​dxbjavid](https://redirect.github.com/dxbjavid) in [tox-dev/filelock#581](https://redirect.github.com/tox-dev/filelock/pull/581) - \_util: drop the dead st_mtime=0 short-circuit in raise_on_not_writable_file by [@​HrachShah](https://redirect.github.com/HrachShah) in [tox-dev/filelock#582](https://redirect.github.com/tox-dev/filelock/pull/582) - test: silence fork DeprecationWarning on 3.15 by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#585](https://redirect.github.com/tox-dev/filelock/pull/585) **Full Changelog**: <https://github.com/tox-dev/filelock/compare/3.29.5...3.29.6> ### [`v3.29.5`](https://redirect.github.com/tox-dev/filelock/releases/tag/3.29.5) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/3.29.4...3.29.5) <!-- Release notes generated using configuration in .github/release.yaml at main --> #### What's Changed - serialise read/write release rollback against a concurrent acquire by [@​dxbjavid](https://redirect.github.com/dxbjavid) in [tox-dev/filelock#563](https://redirect.github.com/tox-dev/filelock/pull/563) - 🔒 fix(soft_rw): refresh held marker through the verified fd by [@​dxbjavid](https://redirect.github.com/dxbjavid) in [tox-dev/filelock#565](https://redirect.github.com/tox-dev/filelock/pull/565) - only unlink the writer marker on release if it is still ours by [@​dxbjavid](https://redirect.github.com/dxbjavid) in [tox-dev/filelock#566](https://redirect.github.com/tox-dev/filelock/pull/566) - don't follow symlinks in raise_on_not_writable_file by [@​dxbjavid](https://redirect.github.com/dxbjavid) in [tox-dev/filelock#567](https://redirect.github.com/tox-dev/filelock/pull/567) - don't complete a writer acquire on a peer's reclaimed marker by [@​dxbjavid](https://redirect.github.com/dxbjavid) in [tox-dev/filelock#571](https://redirect.github.com/tox-dev/filelock/pull/571) - use a private break name in break_lock_file by [@​dxbjavid](https://redirect.github.com/dxbjavid) in [tox-dev/filelock#576](https://redirect.github.com/tox-dev/filelock/pull/576) - Keep Unix lock files after release by [@​itscloud0](https://redirect.github.com/itscloud0) in [tox-dev/filelock#577](https://redirect.github.com/tox-dev/filelock/pull/577) - test: fix Windows type check broken by [#​577](https://redirect.github.com/tox-dev/py-filelock/issues/577) by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#580](https://redirect.github.com/tox-dev/filelock/pull/580) - roll back a read acquire's open transaction when its SELECT fails by [@​dxbjavid](https://redirect.github.com/dxbjavid) in [tox-dev/filelock#575](https://redirect.github.com/tox-dev/filelock/pull/575) - lifetime: reject negative, non-numeric, and bool values at the setter by [@​HrachShah](https://redirect.github.com/HrachShah) in [tox-dev/filelock#573](https://redirect.github.com/tox-dev/filelock/pull/573) #### New Contributors - [@​itscloud0](https://redirect.github.com/itscloud0) made their first contribution in [tox-dev/filelock#577](https://redirect.github.com/tox-dev/filelock/pull/577) - [@​HrachShah](https://redirect.github.com/HrachShah) made their first contribution in [tox-dev/filelock#573](https://redirect.github.com/tox-dev/filelock/pull/573) **Full Changelog**: <https://github.com/tox-dev/filelock/compare/3.29.4...3.29.5> ### [`v3.29.4`](https://redirect.github.com/tox-dev/filelock/releases/tag/3.29.4) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/3.29.3...3.29.4) <!-- Release notes generated using configuration in .github/release.yaml at 3.29.4 --> #### What's Changed - verify inode in break_lock_file before unlinking a stale lock by [@​dxbjavid](https://redirect.github.com/dxbjavid) in [tox-dev/filelock#561](https://redirect.github.com/tox-dev/filelock/pull/561) - keep the read/write heartbeat alive on a transient touch error by [@​dxbjavid](https://redirect.github.com/dxbjavid) in [tox-dev/filelock#562](https://redirect.github.com/tox-dev/filelock/pull/562) **Full Changelog**: <https://github.com/tox-dev/filelock/compare/3.29.3...3.29.4> ### [`v3.29.3`](https://redirect.github.com/tox-dev/filelock/releases/tag/3.29.3) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/3.29.2...3.29.3) <!-- Release notes generated using configuration in .github/release.yaml at 3.29.3 --> #### What's Changed - 🔧 ci(release): publish to PyPI on tag push by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#557](https://redirect.github.com/tox-dev/filelock/pull/557) - validate pid range in \_parse_lock_holder by [@​dxbjavid](https://redirect.github.com/dxbjavid) in [tox-dev/filelock#556](https://redirect.github.com/tox-dev/filelock/pull/556) - 🐛 fix(ci): restore release environment on tag job by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#559](https://redirect.github.com/tox-dev/filelock/pull/559) - 🐛 fix(ci): publish from release.yaml on tag push by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#560](https://redirect.github.com/tox-dev/filelock/pull/560) **Full Changelog**: <https://github.com/tox-dev/filelock/compare/3.29.2...3.29.3> ### [`v3.29.2`](https://redirect.github.com/tox-dev/filelock/releases/tag/3.29.2) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/3.29.1...3.29.2) <!-- Release notes generated using configuration in .github/release.yaml at 3.29.2 --> #### What's Changed - open marker reads non-blocking to refuse attacker-placed fifo by [@​dxbjavid](https://redirect.github.com/dxbjavid) in [tox-dev/filelock#549](https://redirect.github.com/tox-dev/filelock/pull/549) - 🔒 fix(soft): harden stale-lock breaking and self-heal malformed locks by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#551](https://redirect.github.com/tox-dev/filelock/pull/551) - check hostname in is_lock_held_by_us by [@​dxbjavid](https://redirect.github.com/dxbjavid) in [tox-dev/filelock#553](https://redirect.github.com/tox-dev/filelock/pull/553) **Full Changelog**: <https://github.com/tox-dev/filelock/compare/3.29.1...3.29.2> ### [`v3.29.1`](https://redirect.github.com/tox-dev/filelock/releases/tag/3.29.1) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/3.29.0...3.29.1) <!-- Release notes generated using configuration in .github/release.yaml at 3.29.1 --> #### What's Changed - docs: fix API docs of `release()` by [@​MrAnno](https://redirect.github.com/MrAnno) in [tox-dev/filelock#540](https://redirect.github.com/tox-dev/filelock/pull/540) - docs: clarify per-thread scope of FileLock configuration by [@​Gares95](https://redirect.github.com/Gares95) in [tox-dev/filelock#543](https://redirect.github.com/tox-dev/filelock/pull/543) - chore: improve filelock maintenance path by [@​lphuc2250gma](https://redirect.github.com/lphuc2250gma) in [tox-dev/filelock#542](https://redirect.github.com/tox-dev/filelock/pull/542) - chore: improve filelock maintenance path by [@​lphuc2250gma](https://redirect.github.com/lphuc2250gma) in [tox-dev/filelock#544](https://redirect.github.com/tox-dev/filelock/pull/544) - chore: improve filelock maintenance path by [@​lphuc2250gma](https://redirect.github.com/lphuc2250gma) in [tox-dev/filelock#545](https://redirect.github.com/tox-dev/filelock/pull/545) - 🐛 fix(soft): refuse to follow symlinks when reading the lock file by [@​dxbjavid](https://redirect.github.com/dxbjavid) in [tox-dev/filelock#548](https://redirect.github.com/tox-dev/filelock/pull/548) #### New Contributors - [@​MrAnno](https://redirect.github.com/MrAnno) made their first contribution in [tox-dev/filelock#540](https://redirect.github.com/tox-dev/filelock/pull/540) - [@​Gares95](https://redirect.github.com/Gares95) made their first contribution in [tox-dev/filelock#543](https://redirect.github.com/tox-dev/filelock/pull/543) - [@​lphuc2250gma](https://redirect.github.com/lphuc2250gma) made their first contribution in [tox-dev/filelock#542](https://redirect.github.com/tox-dev/filelock/pull/542) - [@​dxbjavid](https://redirect.github.com/dxbjavid) made their first contribution in [tox-dev/filelock#548](https://redirect.github.com/tox-dev/filelock/pull/548) **Full Changelog**: <https://github.com/tox-dev/filelock/compare/3.29.0...3.29.1> </details> --- ### Configuration 📅 **Schedule**: (UTC) - Branch creation - At any time (no schedule defined) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/google-cloud-python). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4xNTUuMiIsInVwZGF0ZWRJblZlciI6IjQ0LjE1NS4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->
parthea
pushed a commit
to googleapis/google-cloud-python
that referenced
this pull request
Oct 16, 2026
This PR contains the following updates: | Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) | |---|---|---|---| | [filelock](https://redirect.github.com/tox-dev/py-filelock) | `==3.32.7` → `==4.2.0` |  |  | --- ### Release Notes <details> <summary>tox-dev/py-filelock (filelock)</summary> ### [`v4.2.0`](https://redirect.github.com/tox-dev/filelock/releases/tag/4.2.0) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/4.1.2...4.2.0) <!-- Release notes generated using configuration in .github/release.yaml at 4.2.0 --> #### What's Changed - fix(strict): skip Windows claims pending deletion by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#829](https://redirect.github.com/tox-dev/filelock/pull/829) - perf(import): defer asyncio and sqlite3 loading by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#831](https://redirect.github.com/tox-dev/filelock/pull/831) **Full Changelog**: <tox-dev/filelock@4.1.2...4.2.0> ### [`v4.1.2`](https://redirect.github.com/tox-dev/filelock/releases/tag/4.1.2) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/4.1.1...4.1.2) <!-- Release notes generated using configuration in .github/release.yaml at 4.1.2 --> #### What's Changed - fix: prioritize S_ISDIR check in raise_on_not_writable_file by [@​feiiiiii5](https://redirect.github.com/feiiiiii5) in [tox-dev/filelock#822](https://redirect.github.com/tox-dev/filelock/pull/822) - 🔧 chore(security): enroll in Anthropic OSS Scanner by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#823](https://redirect.github.com/tox-dev/filelock/pull/823) - 📝 docs(security): add an email reporting contact by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#825](https://redirect.github.com/tox-dev/filelock/pull/825) - docs: hash all keys in the lock filename recipe by [@​xiehuanyi](https://redirect.github.com/xiehuanyi) in [tox-dev/filelock#824](https://redirect.github.com/tox-dev/filelock/pull/824) - fix(read-write): use sqlite_master for read lock schema probe on older SQLite by [@​DawnofGenX](https://redirect.github.com/DawnofGenX) in [tox-dev/filelock#827](https://redirect.github.com/tox-dev/filelock/pull/827) - fix(rw): forget the async lock's worker after fork by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#828](https://redirect.github.com/tox-dev/filelock/pull/828) #### New Contributors - [@​xiehuanyi](https://redirect.github.com/xiehuanyi) made their first contribution in [tox-dev/filelock#824](https://redirect.github.com/tox-dev/filelock/pull/824) **Full Changelog**: <tox-dev/filelock@4.1.1...4.1.2> ### [`v4.1.1`](https://redirect.github.com/tox-dev/filelock/releases/tag/4.1.1) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/4.1.0...4.1.1) <!-- Release notes generated using configuration in .github/release.yaml at 4.1.1 --> #### What's Changed - feat(python): default to Python 3.15 by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#816](https://redirect.github.com/tox-dev/filelock/pull/816) - fix(rw): avoid macOS descriptor lookups by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#820](https://redirect.github.com/tox-dev/filelock/pull/820) - fix(tests): bound concurrent lock progress by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#819](https://redirect.github.com/tox-dev/filelock/pull/819) - test: make lock error checks deterministic by [@​adenzhou1350](https://redirect.github.com/adenzhou1350) in [tox-dev/filelock#817](https://redirect.github.com/tox-dev/filelock/pull/817) - fix(read-write): reject a hostile pid in \_owner_is_gone by [@​dxbjavid](https://redirect.github.com/dxbjavid) in [tox-dev/filelock#821](https://redirect.github.com/tox-dev/filelock/pull/821) #### New Contributors - [@​adenzhou1350](https://redirect.github.com/adenzhou1350) made their first contribution in [tox-dev/filelock#817](https://redirect.github.com/tox-dev/filelock/pull/817) **Full Changelog**: <tox-dev/filelock@4.1.0...4.1.1> ### [`v4.1.0`](https://redirect.github.com/tox-dev/filelock/releases/tag/4.1.0) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/4.0.12...4.1.0) <!-- Release notes generated using configuration in .github/release.yaml at 4.1.0 --> #### What's Changed - ci: download coverage during tool setup by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#776](https://redirect.github.com/tox-dev/filelock/pull/776) - 🐛 fix(api): validate timeout and poll_interval bounds by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#781](https://redirect.github.com/tox-dev/filelock/pull/781) - 🐛 fix(read-write): accept inf and reject nan timeouts by [@​darrenhuai](https://redirect.github.com/darrenhuai) in [tox-dev/filelock#779](https://redirect.github.com/tox-dev/filelock/pull/779) - 🐛 fix(soft-rw): ignore non-ASCII generation names by [@​dxbjavid](https://redirect.github.com/dxbjavid) in [tox-dev/filelock#778](https://redirect.github.com/tox-dev/filelock/pull/778) - 🐛 fix(soft): check start token in is_lock_held_by_us by [@​lprnmns](https://redirect.github.com/lprnmns) in [tox-dev/filelock#774](https://redirect.github.com/tox-dev/filelock/pull/774) - 🐛 fix(soft): clean up marker when rollback close fails by [@​harbinresearcher](https://redirect.github.com/harbinresearcher) in [tox-dev/filelock#775](https://redirect.github.com/tox-dev/filelock/pull/775) - 🐛 fix(read-write): clamp waits to threading.TIMEOUT_MAX by [@​darrenhuai](https://redirect.github.com/darrenhuai) in [tox-dev/filelock#780](https://redirect.github.com/tox-dev/filelock/pull/780) - 🐛 fix(soft): treat truncated markers as malformed by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#782](https://redirect.github.com/tox-dev/filelock/pull/782) - 🐛 fix(acquire): keep every acquire wait within the timeout by [@​feiiiiii5](https://redirect.github.com/feiiiiii5) in [tox-dev/filelock#777](https://redirect.github.com/tox-dev/filelock/pull/777) - 📝 docs: fix hanging example and platform claims by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#783](https://redirect.github.com/tox-dev/filelock/pull/783) - 🐛 fix(unix): keep peer marker on ENOSYS fallback by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#785](https://redirect.github.com/tox-dev/filelock/pull/785) - 🐛 fix(async): clear the task hold after a canceled release by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#789](https://redirect.github.com/tox-dev/filelock/pull/789) - ✨ feat(api): export lease types and has_fcntl by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#790](https://redirect.github.com/tox-dev/filelock/pull/790) - 🐛 fix(strict): age private records by the filesystem clock by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#792](https://redirect.github.com/tox-dev/filelock/pull/792) - 🐛 fix(async): surface executor shutdown as an error by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#793](https://redirect.github.com/tox-dev/filelock/pull/793) - 🐛 fix(soft): expire leases on the contender's clock by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#796](https://redirect.github.com/tox-dev/filelock/pull/796) - 🐛 fix(soft-rw): stop an acquire that close() overtook by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#798](https://redirect.github.com/tox-dev/filelock/pull/798) - 🐛 fix(strict): record claims before linking them by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#787](https://redirect.github.com/tox-dev/filelock/pull/787) - 🐛 fix(soft): restore a live marker a stale break moved aside by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#786](https://redirect.github.com/tox-dev/filelock/pull/786) - 🐛 fix(api): chain errors on 3.10 without exceptiongroup by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#788](https://redirect.github.com/tox-dev/filelock/pull/788) - 🐛 fix(soft): release a dropped SoftFileLease by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#791](https://redirect.github.com/tox-dev/filelock/pull/791) - 🐛 fix(read-write): keep probe fds until the last connection closes by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#794](https://redirect.github.com/tox-dev/filelock/pull/794) - 📦 build(sdist): ship docs and update SECURITY.md by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#812](https://redirect.github.com/tox-dev/filelock/pull/812) - 🐛 fix(soft-rw): survive a removed generation log by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#795](https://redirect.github.com/tox-dev/filelock/pull/795) - 🐛 fix(soft): tell PID namespaces apart in the marker host by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#797](https://redirect.github.com/tox-dev/filelock/pull/797) - 🐛 fix(async): release from the finalizer and keep I/O off the loop by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#800](https://redirect.github.com/tox-dev/filelock/pull/800) - 🐛 fix(strict): name what blocks the lock path by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#804](https://redirect.github.com/tox-dev/filelock/pull/804) - 🐛 fix(read-write): reject WAL databases and link beside the db by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#805](https://redirect.github.com/tox-dev/filelock/pull/805) - 🐛 fix(read-write): track read depth per thread by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#806](https://redirect.github.com/tox-dev/filelock/pull/806) - 🐛 fix(soft): honour mode and tighten marker grammar by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#807](https://redirect.github.com/tox-dev/filelock/pull/807) - 🧪 test: drop timing races from two runner-load flakes by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#809](https://redirect.github.com/tox-dev/filelock/pull/809) - 🐛 fix(descriptor): reject poll intervals above TIMEOUT_MAX by [@​sricharanreddycheruku](https://redirect.github.com/sricharanreddycheruku) in [tox-dev/filelock#802](https://redirect.github.com/tox-dev/filelock/pull/802) - 🐛 fix(api): validate lock options up front by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#803](https://redirect.github.com/tox-dev/filelock/pull/803) - 🐛 fix(soft-rw): publish the head through gen/HEAD by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#799](https://redirect.github.com/tox-dev/filelock/pull/799) - 🐛 fix(api): release thread holds, guard reentry by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#810](https://redirect.github.com/tox-dev/filelock/pull/810) - 🧪 test(lease): give the age-out test a real-time margin by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#814](https://redirect.github.com/tox-dev/filelock/pull/814) - 📝 docs: point canonical and og:url at versioned pages by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#813](https://redirect.github.com/tox-dev/filelock/pull/813) - 🐛 fix(read-write): refuse a database moved mid-acquire by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#808](https://redirect.github.com/tox-dev/filelock/pull/808) - 🐛 fix: close regressions since 4.0.12 by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#815](https://redirect.github.com/tox-dev/filelock/pull/815) #### New Contributors - [@​darrenhuai](https://redirect.github.com/darrenhuai) made their first contribution in [tox-dev/filelock#779](https://redirect.github.com/tox-dev/filelock/pull/779) - [@​harbinresearcher](https://redirect.github.com/harbinresearcher) made their first contribution in [tox-dev/filelock#775](https://redirect.github.com/tox-dev/filelock/pull/775) - [@​sricharanreddycheruku](https://redirect.github.com/sricharanreddycheruku) made their first contribution in [tox-dev/filelock#802](https://redirect.github.com/tox-dev/filelock/pull/802) **Full Changelog**: <tox-dev/filelock@4.0.12...4.1.0> ### [`v4.0.12`](https://redirect.github.com/tox-dev/filelock/releases/tag/4.0.12) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/4.0.11...4.0.12) <!-- Release notes generated using configuration in .github/release.yaml at 4.0.12 --> #### What's Changed - fix: support older SQLite read locks by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#771](https://redirect.github.com/tox-dev/filelock/pull/771) **Full Changelog**: <tox-dev/filelock@4.0.11...4.0.12> ### [`v4.0.11`](https://redirect.github.com/tox-dev/filelock/releases/tag/4.0.11) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/4.0.10...4.0.11) <!-- Release notes generated using configuration in .github/release.yaml at 4.0.11 --> #### What's Changed - docs: select an existing tox environment in contributing guide by [@​raghav-sharma-ai](https://redirect.github.com/raghav-sharma-ai) in [tox-dev/filelock#767](https://redirect.github.com/tox-dev/filelock/pull/767) - fix(read-write): handle NetBSD fd limits by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#768](https://redirect.github.com/tox-dev/filelock/pull/768) #### New Contributors - [@​raghav-sharma-ai](https://redirect.github.com/raghav-sharma-ai) made their first contribution in [tox-dev/filelock#767](https://redirect.github.com/tox-dev/filelock/pull/767) **Full Changelog**: <tox-dev/filelock@4.0.10...4.0.11> ### [`v4.0.10`](https://redirect.github.com/tox-dev/filelock/releases/tag/4.0.10) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/4.0.9...4.0.10) <!-- Release notes generated using configuration in .github/release.yaml at 4.0.10 --> #### What's Changed - ♻️ refactor(util): test helpers via public locks by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#764](https://redirect.github.com/tox-dev/filelock/pull/764) - 🐛 fix(singleton): reject conflicting async and lease options by [@​kokotatan](https://redirect.github.com/kokotatan) in [tox-dev/filelock#765](https://redirect.github.com/tox-dev/filelock/pull/765) #### New Contributors - [@​kokotatan](https://redirect.github.com/kokotatan) made their first contribution in [tox-dev/filelock#765](https://redirect.github.com/tox-dev/filelock/pull/765) **Full Changelog**: <tox-dev/filelock@4.0.9...4.0.10> ### [`v4.0.9`](https://redirect.github.com/tox-dev/filelock/releases/tag/4.0.9) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/4.0.8...4.0.9) <!-- Release notes generated using configuration in .github/release.yaml at 4.0.9 --> #### What's Changed - 📝 docs(util): correct write and break guarantees by [@​pralav-25](https://redirect.github.com/pralav-25) in [tox-dev/filelock#762](https://redirect.github.com/tox-dev/filelock/pull/762) - 🐛 fix(read-write): close db fd after connect by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#763](https://redirect.github.com/tox-dev/filelock/pull/763) #### New Contributors - [@​pralav-25](https://redirect.github.com/pralav-25) made their first contribution in [tox-dev/filelock#762](https://redirect.github.com/tox-dev/filelock/pull/762) **Full Changelog**: <tox-dev/filelock@4.0.8...4.0.9> ### [`v4.0.8`](https://redirect.github.com/tox-dev/filelock/releases/tag/4.0.8) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/4.0.7...4.0.8) <!-- Release notes generated using configuration in .github/release.yaml at 4.0.8 --> #### What's Changed - 🐛 fix(read-write): refuse cross-thread write release by [@​feiiiiii5](https://redirect.github.com/feiiiiii5) in [tox-dev/filelock#761](https://redirect.github.com/tox-dev/filelock/pull/761) **Full Changelog**: <tox-dev/filelock@4.0.7...4.0.8> ### [`v4.0.7`](https://redirect.github.com/tox-dev/filelock/releases/tag/4.0.7) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/4.0.6...4.0.7) <!-- Release notes generated using configuration in .github/release.yaml at 4.0.7 --> #### What's Changed - 🐛 fix(mode): require owner read and write by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#760](https://redirect.github.com/tox-dev/filelock/pull/760) **Full Changelog**: <tox-dev/filelock@4.0.6...4.0.7> ### [`v4.0.6`](https://redirect.github.com/tox-dev/filelock/releases/tag/4.0.6) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/4.0.5...4.0.6) <!-- Release notes generated using configuration in .github/release.yaml at 4.0.6 --> #### What's Changed - fix(read-write): validate reentrant timeouts by [@​feiiiiii5](https://redirect.github.com/feiiiiii5) in [tox-dev/filelock#756](https://redirect.github.com/tox-dev/filelock/pull/756) **Full Changelog**: <tox-dev/filelock@4.0.5...4.0.6> ### [`v4.0.5`](https://redirect.github.com/tox-dev/filelock/releases/tag/4.0.5) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/4.0.4...4.0.5) <!-- Release notes generated using configuration in .github/release.yaml at 4.0.5 --> #### What's Changed - fix(marker): preserve live owners by [@​DawnofGenX](https://redirect.github.com/DawnofGenX) in [tox-dev/filelock#751](https://redirect.github.com/tox-dev/filelock/pull/751) - fix(tests): separate mode and access checks by [@​pasmud](https://redirect.github.com/pasmud) in [tox-dev/filelock#753](https://redirect.github.com/tox-dev/filelock/pull/753) - fix(read-write): honor instance defaults by [@​DawnofGenX](https://redirect.github.com/DawnofGenX) in [tox-dev/filelock#752](https://redirect.github.com/tox-dev/filelock/pull/752) - fix(async): validate blocking read-write timeouts by [@​pasmud](https://redirect.github.com/pasmud) in [tox-dev/filelock#755](https://redirect.github.com/tox-dev/filelock/pull/755) - fix(strict): handle vanished unreadable claims by [@​januththedev](https://redirect.github.com/januththedev) in [tox-dev/filelock#754](https://redirect.github.com/tox-dev/filelock/pull/754) #### New Contributors - [@​DawnofGenX](https://redirect.github.com/DawnofGenX) made their first contribution in [tox-dev/filelock#751](https://redirect.github.com/tox-dev/filelock/pull/751) - [@​pasmud](https://redirect.github.com/pasmud) made their first contribution in [tox-dev/filelock#753](https://redirect.github.com/tox-dev/filelock/pull/753) - [@​januththedev](https://redirect.github.com/januththedev) made their first contribution in [tox-dev/filelock#754](https://redirect.github.com/tox-dev/filelock/pull/754) **Full Changelog**: <tox-dev/filelock@4.0.4...4.0.5> ### [`v4.0.4`](https://redirect.github.com/tox-dev/filelock/releases/tag/4.0.4) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/4.0.3...4.0.4) <!-- Release notes generated using configuration in .github/release.yaml at 4.0.4 --> #### What's Changed - 🐛 fix(identity): digest the cut tail of long hostnames by [@​feiiiiii5](https://redirect.github.com/feiiiiii5) in [tox-dev/filelock#748](https://redirect.github.com/tox-dev/filelock/pull/748) #### New Contributors - [@​feiiiiii5](https://redirect.github.com/feiiiiii5) made their first contribution in [tox-dev/filelock#748](https://redirect.github.com/tox-dev/filelock/pull/748) **Full Changelog**: <tox-dev/filelock@4.0.3...4.0.4> ### [`v4.0.3`](https://redirect.github.com/tox-dev/filelock/releases/tag/4.0.3) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/4.0.2...4.0.3) <!-- Release notes generated using configuration in .github/release.yaml at 4.0.3 --> #### What's Changed - 🐛 fix(api): skip the fork audit hook on CPython <3.12 by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#747](https://redirect.github.com/tox-dev/filelock/pull/747) **Full Changelog**: <tox-dev/filelock@4.0.2...4.0.3> ### [`v4.0.2`](https://redirect.github.com/tox-dev/filelock/releases/tag/4.0.2) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/4.0.1...4.0.2) <!-- Release notes generated using configuration in .github/release.yaml at 4.0.2 --> #### What's Changed - docs: create the data directory in the async cache example by [@​agammann](https://redirect.github.com/agammann) in [tox-dev/filelock#740](https://redirect.github.com/tox-dev/filelock/pull/740) - fix: ignore broken sphinx-llm release by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#742](https://redirect.github.com/tox-dev/filelock/pull/742) - 🐛 fix(api): serialize concurrent transitions on shared locks by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#745](https://redirect.github.com/tox-dev/filelock/pull/745) - 🐛 fix(async-rw): give each task its own hold by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#746](https://redirect.github.com/tox-dev/filelock/pull/746) #### New Contributors - [@​agammann](https://redirect.github.com/agammann) made their first contribution in [tox-dev/filelock#740](https://redirect.github.com/tox-dev/filelock/pull/740) **Full Changelog**: <tox-dev/filelock@4.0.1...4.0.2> ### [`v4.0.1`](https://redirect.github.com/tox-dev/filelock/releases/tag/4.0.1) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/4.0.0...4.0.1) <!-- Release notes generated using configuration in .github/release.yaml at 4.0.1 --> #### What's Changed - fix: reject invalid poll_interval before sleep by [@​Pitchfork-and-Torch](https://redirect.github.com/Pitchfork-and-Torch) in [tox-dev/filelock#739](https://redirect.github.com/tox-dev/filelock/pull/739) #### New Contributors - [@​Pitchfork-and-Torch](https://redirect.github.com/Pitchfork-and-Torch) made their first contribution in [tox-dev/filelock#739](https://redirect.github.com/tox-dev/filelock/pull/739) **Full Changelog**: <tox-dev/filelock@4.0.0...4.0.1> ### [`v4.0.0`](https://redirect.github.com/tox-dev/filelock/releases/tag/4.0.0) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/3.32.7...4.0.0) <!-- Release notes generated using configuration in .github/release.yaml at 4.0.0 --> #### What's Changed - 🐛 fix(soft-rw): replace the state mutex with a generation log by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#738](https://redirect.github.com/tox-dev/filelock/pull/738) **Full Changelog**: <tox-dev/filelock@3.32.7...4.0.0> </details> --- ### Configuration 📅 **Schedule**: (UTC) - Branch creation - At any time (no schedule defined) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/google-cloud-python). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4xNTUuMiIsInVwZGF0ZWRJblZlciI6IjQ0LjE1Ni4zIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A
thread_local=Truelock, the default, kept each thread's descriptor inside athreading.local. When the lock was dropped on another thread,__del__calledrelease(force=True), found no descriptor in its own thread's view and returned. The owning thread's fd and kernel lock then stayed held for the life of the process, and so did its deadlock-registry entry, which made a later same-path instance in that thread fail with a misleadingDeadlockerror. 🐛 The same leak happened whenever a thread exited without releasing, since nothing could reach its hold afterwards. The__del__docstring promised that a dropped reference never leaks a held lock.ThreadLocalFileContextnow keeps each thread's state in a plainFileLockContext, and the lock records every committed hold together with its thread. To release another thread's hold, the calling thread points its own view at that state for the duration of a normal release, so every backend's existing release path runs unchanged.__del__releases every thread's hold, since no reference is left through which a thread could still be inside the lock.release(force=True)also releases holds whose thread has exited, and it leaves a running thread's hold alone. Threads contend through separate descriptors, so tearing down a live peer would drop its exclusion in the middle of its critical section.The second fix covers
release()re-entered from a signal handler. The backend kept the descriptor set until its unlock returned, so a handler that calledrelease()in that window unlocked and closed the descriptor, and the interrupted frame then closed the same number again. If another file had reused that number in between, filelock closed it, and the default Unixclose_error_policyhid theEBADF. A per-contextreleasingflag now turns the nested call into a no-op, and the interrupted release finishes the job. The how-to used to recommendrelease(force=True)inside aSIGTERMhandler; it now recommends raising from the handler and lettingwithorfinallyrelease the lock.SoftFileLeasekeeps its claim and heartbeat in a separate thread-local, so releasing an exited thread's lease hold from another thread closes the marker but leaves that thread's heartbeat running until it notices the marker is gone. Async locks keep their own context class and default tothread_local=False, so this change does not touch them.