lockutil

package
v0.4.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 17, 2026 License: MIT Imports: 4 Imported by: 0

Documentation

Overview

Package lockutil provides the platform-specific file primitives behind the O_EXCL lock files in cron, daemon, hooks, oauth, and swarm: a no-overwrite restore for locks that were sidelined during a stale-reclaim attempt, and a lock file remover with one cross-platform contract (missing files are a no-op; Windows retries transient sharing violations).

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ReclaimStaleLock

func ReclaimStaleLock(lockPath, suffix string, isLive func(reclaimedPath string) bool) (bool, error)

ReclaimStaleLock atomically reclaims a suspected-stale lock file. It renames lockPath aside to "<lockPath>.stale.<suffix>" (only one racer can win the rename of a given file, so two racers can never both reclaim the same lock), then consults isLive on the moved file; if the lock turns out to be live (a holder reacquired it in the gap between the caller's stale check and the rename) it is restored rather than stolen. The suffix must be unique per acquirer attempt. Returns true only when a genuinely stale lock was removed, so the caller knows it is safe to retry its exclusive create immediately; on a lost race it returns false. A non-nil error means either the rename aside failed for a reason that is not contention (so retrying cannot help and the caller should fail fast instead of spinning to its deadline), or a live holder's lock could not be restored (both restoreLiveLock's fast path and its no-replace fallback failed), so lockPath may be missing; callers must fail closed instead of re-acquiring. The sidelined file is removed on every restore failure: once the restore has failed it has no protocol function (release only consults the lock path), so keeping it would only leak files.

The live-restore path has an inherent, unclosed race: between the rename aside above and restoreLiveLock putting the lock back, lockPath does not exist, so an unrelated caller's O_EXCL create can legitimately succeed there. restoreLiveLock's fast path then silently overwrites that new claimant's lock file, which does not corrupt release (it is ownership-aware, so the new claimant's later release safely no-ops against content it no longer owns) but does mean the new claimant can still run its critical section concurrently with the original live holder. Making this race actually impossible would need an OS-level advisory lock (flock / LockFileEx) held for a holder's whole critical section, checked non-destructively instead of by moving the file; restoreLiveLock only shrinks the window to roughly one syscall, it does not close it.

func RemoveLockFile

func RemoveLockFile(path string) error

RemoveLockFile removes a lock file on non-Windows platforms. Removing an already-missing file reports nil, matching the Windows implementation, so callers see one cross-platform contract.

func RestoreLockFile

func RestoreLockFile(reclaimed, path string) error

RestoreLockFile restores a sidelined lock file on non-Windows platforms. It uses os.Link so a competing lock created at path in the meantime wins: the link fails with os.ErrExist instead of overwriting it. If the link fails for any other reason (hardlink-incapable filesystems such as FAT or some FUSE/network mounts, ENOSPC, EPERM), it falls back to an O_EXCL copy rather than leaving path missing and the live holder's lock stranded in reclaimed. Once the lock is back at path the restore has succeeded, so a failed cleanup of the sidelined name is not reported as an error; the leftover file is invisible to the lock protocol.

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL