Documentation ¶
Overview ¶
Package lockfile implements convenient lock file utilities for Unix-based systems.
Removable Lock Files - The Difficulty ¶
Removable lock files are notoriously difficult to get right. On BSD systems, doing this in a race-free manner is trivial, via O_EXLOCK in an open(2) call, but this is generally unavailable on Unix-like systems due to Linux's lack of support for this option.
Consider several processes' hypothetical sequences of open, lock, close (thus implicitly removing the kernel advisory lock), and unlink.
A B C open open lock close lock unlink open lock
Now B thinks it's got a lock, but its lock file has been removed. C has opened the same lock file name, thus creating a new file, and locked it. So now B and C both think they've got the lock. Game over.
You might attempt re-arranging the close and unlink calls, but the problem remains. In general, if B opens the same file as A, and B locks after A closes, then B can have a lock on a dangling file descriptor.
The general problem is that the close and unlink steps are not atomic.
Removable Lock Files - A Solution ¶
One solution is to guard the two halves of the removable lock file operations, open and lock, and close and unlink, with another lock file that is itself not removed. This is the approach that this package takes with LockRm. Using this approach, removable lock files may be implemented in a race-free manner.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type LockContext ¶
type LockContext struct {
// contains filtered or unexported fields
}
LockContext represents a locked file, and is obtained by calling Lock or LockNb.
func Lock ¶
func Lock(filename string) (*LockContext, error)
Lock locks on the filename given and returns a new LockContext, on which you can later call Unlock. This implementation blocks, and does not clean up the lock file on Unlock.
func LockNb ¶
func LockNb(filename string) (*LockContext, error)
LockNb locks on the filename given and returns a new LockContext, on which you can later call Unlock. This implementation does not block, and does not clean up the lock file on Unlock.
func (*LockContext) Unlock ¶
func (lc *LockContext) Unlock()
Unlock unlocks the lock file represented by the LockContext.
type LockRmContext ¶
type LockRmContext struct {
// contains filtered or unexported fields
}
LockRmContext represents a locked file that can be removed on Unlock, and is obtained by calling LockRm.
func LockRm ¶
func LockRm(globalname, localname string) (*LockRmContext, error)
LockRm implements a removable lock file, specified by localname. This implementation does not block, and removes the lock file on Unlock.
On BSD systems, doing this in a race-free manner is trivial, via O_EXLOCK in an open(2) call, but this is generally unavailable on Unix-like systems due to Linux's lack of support for this option.
With the normal facilities provided, removing a lock file on unlock creates race conditions. However, if the "local" lock file operations are secured by use of a "global" lock file, which is itself not removed, this can be implemented in a race-free manner.
func (*LockRmContext) Unlock ¶
func (lrc *LockRmContext) Unlock() error
Unlock unlocks and removes the lock file represented by the LockRmContext.