6.0.0-rc4Source

QLockFile Class

The QLockFile class provides locking between processes using a file. More…

Header#include <QLockFile>
CMaketarget_link_libraries(app PRIVATE Nt::Core)
ModuleNt Core C++ Classes

List of all members, including inherited members

Public Types

enumLockError

Public Functions

QLockFile(const QString &fileName)
~QLockFile()
boollock()
booltryLock(int timeout = 0)
booltryLock(std::chrono::milliseconds timeout)
voidunlock()
voidsetStaleLockTime(int staleLockTime)
intstaleLockTime() const
voidsetStaleLockTime(std::chrono::milliseconds value)
std::chrono::millisecondsstaleLockTimeAsDuration() const
QStringfileName() const
boolisLocked() const
boolgetLockInfo(qint64 *pid, QString *hostname, QString *appname) const
boolremoveStaleLockFile()
LockErrorerror() const

Detailed Description

A lock file can be used to prevent multiple processes from accessing a same resource. For instance, a configuration file on disk, or a socket, a port, a region of shared memory...

Serialization is only guaranteed if all processes that access the shared resource use QLockFile, with the same file name.

QLockFile supports two use cases: protecting a resource for a short period of time (a few seconds at most) and for a long time.

QLockFile lockFile("/tmp/app.lock");
if (lockFile.tryLock(2000)) {
    useResource();
    lockFile.unlock();
} else if (lockFile.error() == QLockFile::LockFailedError) {
    qint64 pid;
    QString host, app;
    lockFile.getLockInfo(&pid, &host, &app);
}

The lock file is created with the process id, application path and host name of the owner in it, so that other processes can find out who holds the lock. If the owning process dies without unlocking, the lock file is detected as stale: on the same host, because its process no longer exists (or the pid belongs to another program), and on any host once the file is older than staleLockTime(). A stale lock is then removed, with a second lock file named .rmlock making sure that two processes do not remove it at the same time.

The file is created atomically: it is written under a temporary name in the same directory and then hard linked to the lock file name, so that other processes never see a partial file. If the file system does not support hard links, the lock file is created directly.

See also QFile and QSaveFile.

Differences from Qt

Calling lock() or tryLock() on a lock that this object already holds prints a warning and fails with LockFailedError instead of waiting. While waiting, the polling interval starts at 10 ms and doubles up to half a second. An unlock() that finds the lock file replaced by another process leaves the other file alone. The application path in the lock file is the executable path from /proc, and a lock file whose application name is not an absolute path is not checked for a reused pid. The lock is not re-created if the file is removed by another process.

Member Type Documentation

enum QLockFile::LockError

This enum describes the result of the last call to lock() or tryLock().

ConstantDescription
QLockFile::NoErrorThe lock was acquired successfully.
QLockFile::LockFailedErrorThe lock could not be acquired because another process holds it.
QLockFile::PermissionErrorThe lock file could not be created, for lack of permissions in the parent directory.
QLockFile::UnknownErrorAnother error happened, for instance a full partition prevented writing out the lock file, or the directory of the lock file does not exist.

Member Function Documentation

[explicit] QLockFile::QLockFile(const QString &fileName)

Constructs a new lock file object. The object is created in an unlocked state. When calling lock() or tryLock(), a lock file named fileName will be created, if it doesn't already exist.

See also lock() and unlock().

QLockFile::~QLockFile()

Destroys the lock file object. If the lock was acquired, this will release the lock, by deleting the lock file.

LockError QLockFile::error() const

Returns the lock file error status.

If tryLock() returns false, this function can be called to find out the reason why the locking failed.

See also tryLock().

QString QLockFile::fileName() const

Returns the name of the lock file, as given to the constructor.

This function was introduced in 6.6.

bool QLockFile::getLockInfo(qint64 *pid, QString *hostname, QString *appname) const

Retrieves information about the current owner of the lock file.

If tryLock() returns false, and error() returns LockFailedError, this function can be called to find out more information about the existing lock file: pid is the process id of the process that created it, hostname the host it ran on and appname the application it ran. Returns true if the information could be retrieved, in which case the outputs that are not nullptr are set; otherwise returns false.

See also tryLock() and error().

bool QLockFile::isLocked() const

Returns true if the lock was acquired by this QLockFile instance, otherwise returns false.

See also lock(), unlock() and tryLock().

bool QLockFile::lock()

Creates the lock file. If another process (or thread) has created the lock file already, this function will block until that process (or thread) releases it. Calling this function multiple times on the same lock from the same thread without unlocking first is not allowed.

Returns true if the lock was acquired, false if it could not be acquired due to an unrecoverable error, such as no permissions in the parent directory.

See also unlock(), tryLock() and error().

bool QLockFile::removeStaleLockFile()

Attempts to forcefully remove an existing lock file.

Calling this is not recommended when protecting a short-lived operation: QLockFile already takes care of removing lock files after a crash, based on a time-out and a check that the process that created the lock file is still running. Also, this function is not guaranteed to remove the lock file if it is held by another process; it only deletes the file. The lock file must not be locked by this object.

Returns true if the lock file was removed.

See also setStaleLockTime() and getLockInfo().

void QLockFile::setStaleLockTime(int staleLockTime)

Sets the time in milliseconds after which a lock file is considered stale to staleLockTime. The default value is 30000, i.e. 30 seconds. If your application typically keeps the file locked for more than 30 seconds (for instance while saving megabytes of data for 2 minutes), you should set a bigger value using setStaleLockTime().

The value is used by lock() and tryLock() in order to determine when an existing lock file is considered stale, i.e. left over by a crashed process. This is done by checking the modification time of the lock file, in addition to checking whether the process that created it still exists on the same host. A value of 0 or less disables the check of the modification time.

See also staleLockTime().

void QLockFile::setStaleLockTime(std::chrono::milliseconds value)

This is an overloaded function.

Sets the time after which a lock file is considered stale to value.

This function was introduced in 6.2.

See also staleLockTimeAsDuration().

int QLockFile::staleLockTime() const

Returns the time in milliseconds after which a lock file is considered stale.

See also setStaleLockTime().

std::chrono::milliseconds QLockFile::staleLockTimeAsDuration() const

Returns the time after which a lock file is considered stale, as a duration.

This function was introduced in 6.2.

See also staleLockTime() and setStaleLockTime().

bool QLockFile::tryLock(int timeout = 0)

Attempts to create the lock file. This function returns true if the lock was obtained; otherwise it returns false. If another process (or thread) has created the lock file already, this function will wait for at most timeout milliseconds for the lock file to become available.

Note: Passing a negative number as the timeout is equivalent to calling lock(), i.e. this function will wait forever until the lock file can be locked if timeout is negative.

If the lock was obtained, it must be released with unlock() before another process (or thread) can successfully lock it.

Calling this function multiple times on the same lock from the same thread without unlocking first is not allowed; it fails.

See also lock() and unlock().

bool QLockFile::tryLock(std::chrono::milliseconds timeout)

This is an overloaded function.

Tries to create the lock file like tryLock(int), waiting for at most timeout. A negative timeout waits for as long as it takes.

This function was introduced in 6.2.

void QLockFile::unlock()

Releases the lock, by deleting the lock file. Calling this function without having successfully obtained the lock is a no-op.

See also lock() and tryLock().