filelock
A simple file locking library for Rust. On Rust 1.89 and newer, locking uses
the standard library's std::fs::File::lock API. Rust 1.71 through 1.88 use a
backport of that implementation from Rust 1.97.1, preserving the same
platform behavior and interoperability.
Image by Homutan, source: https://www.pixiv.net/artworks/128080460
Installation
Usage
Acquire an exclusive lock, and let the guard release it:
filelock::new opens (and creates if missing) the lock file, and the file
stays open for the lifetime of the FileLock, so repeated lock/unlock cycles
reuse the same file descriptor or handle. All operations return
std::io::Result.
A guard can also be released manually, which reports errors instead of ignoring them:
Non-blocking, shared, and bounded waits
try_lock attempts to lock without waiting, and lock_timeout waits with an
upper bound. Shared (read) locks allow multiple holders at once, while still
excluding exclusive locks:
use Duration;
Owned guards
The guards returned by lock() and friends borrow the FileLock. When a
guard needs to outlive the current scope, for example stored in a struct or
moved into a spawned task, use the owned variants (lock_owned,
lock_shared_owned, and with the tokio feature lock_owned_async /
lock_shared_owned_async), which take ownership of the FileLock and return
it on unlock:
Using an existing file
An already-open std::fs::File can be locked via FileLock::from_file,
which allows customizing how the lock file is opened. While the lock is held,
the underlying file is accessible through the guard's file() method, for
example to store the holder's process id in the lock file:
On Windows, from_file also supports handles opened for overlapped I/O.
Tokio
Enable the optional tokio feature to wait for a contended lock without
blocking a Tokio runtime worker:
async
lock_async() and lock_shared_async() use non-blocking lock attempts and
asynchronous, bounded backoff, so lock contention does not park a Tokio
runtime worker. They can be used with tokio::time::timeout or
tokio::select!, and cancelling the wait does not leave a blocking task
running in the background. Waiting is polling-based, with the same caveats as
lock_timeout: acquisition can lag the lock's release by up to 50ms, and
waiters are not queued in FIFO order under sustained contention. Do not call
the synchronous lock() from a Tokio runtime worker when the lock may be
contended.
Platform behavior
On Linux, the BSDs, Apple platforms, Illumos, AIX, and the other Unix targets
supported by the standard-library implementation, locks use flock. Solaris
uses fcntl record locks covering the entire file. Windows uses LockFileEx.
Other targets return std::io::ErrorKind::Unsupported from lock operations.
- Every participant must use this locking protocol and resolve the same stable lock-file path. Do not delete, rename, or replace the lock file while participants may be running; doing so can let processes lock different underlying files.
- Locks are advisory and associated with the opened file, not its path. Uncooperative processes can still access the lock file, and a process must not
forkwhile holding a guard and then let both parent and child continue through the protected critical section. - Lock files are opened read-write and, on Unix, created with mode
0644before applying the process umask. Cross-user locking therefore requires permissions to be arranged explicitly. - Interactions between file locks and ordinary reads and writes by non-lockholders are platform specific; see the
std::fs::File::lockdocumentation for details. - Network filesystem behavior depends on the operating system, filesystem, mount options, and server. Validate the required semantics before using a lock file on NFS, SMB, or another remote filesystem.
Minimum supported Rust version
Rust 1.71, including when the optional tokio feature is enabled. Builds with
Rust 1.89 and newer use the standard library's native file-lock API; Rust
1.71–1.88 automatically use the bundled compatibility implementation. This
backend selection is internal and does not change the public API.
The compatibility implementation is derived from the Rust 1.97.1 standard library's Unix and Windows file-locking implementations, which are licensed under Apache-2.0 OR MIT. Source and license attribution is retained in the corresponding implementation files.
Documentation
See https://docs.rs/filelock/latest/filelock/.
License
Filelock is distributed by a MIT license.