-
-
Save shmsr/e12827551ae6694de8ed94a6d5aa562a to your computer and use it in GitHub Desktop.
Examples of using advisory locking with golang.org/x/sys/unix
This file contains 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
// These funcitons ought to come with a huge warning. Using them without | |
// understanding the differences between blocking and non-blocking, or | |
// between exclusive and shared access, and when to use them will cause | |
// problems that do not necessarily manifest right away, but rather | |
// fester in your program and rear their ugly head in the middle of the | |
// night when you're sleeping. | |
// | |
// If you use advisory file locking, *always* use Shared locking every | |
// single time you read the file, and *always* use Exclusive locking every | |
// single time you write the file. Period. There are no exceptions. Heed | |
// this advice, or make your life, or the life of someone who is woken up | |
// in the middle of the night, worse. | |
// withExclusiveBlocking opens the file for reading and writing, creating it | |
// when necessary, and attempts to obtain an exclusive advisory lock on the | |
// file, blocking until the file lock is obtained. It returns the error if it | |
// cannot open the file or cannot obtain an exclusive advisory lock on the file. | |
func withExclusiveBlocking(pathname string, callback func(*os.File)) error { | |
fh, err := os.OpenFile(pathname, os.O_RDWR|os.O_CREATE, os.ModePerm) | |
if err != nil { | |
return err | |
} | |
defer fh.Close() | |
if err = unix.Flock(int(fh.Fd()), unix.LOCK_EX); err != nil { | |
return err | |
} | |
callback(fh) | |
return nil | |
} | |
// withExclusiveNonBlocking opens the file for reading and writing, creating it | |
// when necessary, and attempts to obtain an exclusive advisory lock on the file | |
// without blocking. It returns the error if it cannot open the file, or if it | |
// cannot obtain the exclusive advisory lock on the file. | |
func withExclusiveNonBlocking(pathname string, callback func(*os.File)) error { | |
fh, err := os.OpenFile(pathname, os.O_RDWR|os.O_CREATE, os.ModePerm) | |
if err != nil { | |
return err | |
} | |
defer fh.Close() | |
if err = unix.Flock(int(fh.Fd()), unix.LOCK_EX|unix.LOCK_NB); err != nil { | |
return err | |
} | |
callback(fh) | |
return nil | |
} | |
// withSharedBlocking opens the file for reading, creating it when necessary, | |
// and attempts to obtain a shared advisory lock on the file, blocking until the | |
// file lock is obtained. It returns the error if it cannot open the file or | |
// cannot obtain a shared advisory lock on the file. | |
func withSharedBlocking(pathname string, callback func(*os.File)) error { | |
fh, err := os.Open(pathname) | |
if err != nil { | |
return err | |
} | |
defer fh.Close() | |
if err = unix.Flock(int(fh.Fd()), unix.LOCK_SH); err != nil { | |
return err | |
} | |
callback(fh) | |
return nil | |
} | |
// withSharedNonBlocking opens the file for reading, creating it when necessary, | |
// and attempts to obtain a sahred advisory lock on the file without | |
// blocking. It returns the error if it cannot open the file, or if it cannot | |
// obtain the shared advisory lock on the file. | |
func withSharedNonBlocking(pathname string, callback func(*os.File)) error { | |
fh, err := os.Open(pathname) | |
if err != nil { | |
return err | |
} | |
defer fh.Close() | |
if err = unix.Flock(int(fh.Fd()), unix.LOCK_SH|unix.LOCK_NB); err != nil { | |
return err | |
} | |
callback(fh) | |
return nil | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment