PySide6.QtCore.QLockFile¶
- class QLockFile¶
The
QLockFileclass provides locking between processes using a file. More…Synopsis¶
Methods¶
def
__init__()def
error()def
fileName()def
getLockInfo()def
isLocked()def
lock()def
staleLockTime()def
tryLock()def
unlock()
Note
This documentation may contain snippets that were automatically translated from C++ to Python. We always welcome contributions to the snippet translation. If you see an issue with the translation, you can also let us know by creating a ticket on https:/bugreports.qt.io/projects/PYSIDE
Detailed Description¶
A lock file can be used to prevent multiple processes from accessing concurrently the 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 path.QLockFilesupports two use cases: to protect a resource for a short-term operation (e.g. verifying if a configuration file has changed before saving new settings), and for long-lived protection of a resource (e.g. a document opened by a user in an editor) for an indefinite amount of time.When protecting for a short-term operation, it is acceptable to call
lock()and wait until any running operation finishes. When protecting a resource over a long time, however, the application should always callsetStaleLockTime()(0ms) and thentryLock()with a short timeout, in order to warn the user that the resource is locked.If the process holding the lock crashes, the lock file stays on disk and can prevent any other process from accessing the shared resource, ever. For this reason,
QLockFiletries to detect such a “stale” lock file, based on the process ID written into the file. To cover the situation that the process ID got reused meanwhile, the current process name is compared to the name of the process that corresponds to the process ID from the lock file. If the process names differ, the lock file is considered stale. Additionally, the last modification time of the lock file (30s by default, for the use case of a short-lived operation) is taken into account. If the lock file is found to be stale, it will be deleted.For the use case of protecting a resource over a long time, you should therefore call
setStaleLockTime()(0), and whentryLock()returnsLockFailedError, inform the user that the document is locked, possibly usinggetLockInfo()for more details.Limitations¶
QLockFile‘s implementation is usually safe, for the majority of environments and filesystems. There are a few situations in which it can incorrectly conclude a lock file is stale when it isn’t, fail to detect a stale file, or race when locking. This section documents those issues.There are two main mitigation strategies: choosing a suitable, non-zero
staleLockTime()and choosing a regular, local filesystem for storing lock files (such as/var/lockif running as root on Unix systems or theruntime location). That may not be possible for certain use-cases ofQLockFile, such as when usingQLockFileto indicate a file path provided by the user is being edited.Non-persistent machine IDs¶
QLockFileuses the machine’s unique ID to differentiate a lock by the current machine and one by a process running on a different host. If the machine ID changes over time (such as on systems with ephemeral storage, which must generate a new ID at every boot),QLockFilewill be unable to detect that a lock file is stale after a reboot.Conversely, if two different machines have colliding machine IDs (for example, a cloned system image or restoration from backups) and provide a network path to
QLockFile, the class may conclude the lock is stale when it actually is not.Absence of native locking¶
QLockFileuses operating-system specific calls to indicate to other processes and threads that the lock is alive (not stale), even past thestaleLockTime()setting. This functionality may be absent for files on some networked or virtual filesystems (such as FUSE on Linux and macOS), when using different filesystems to access the same file if the native lock isn’t carried through, or in certain environments that block the necessary system calls.If the native locking support is absent,
QLockFilewill rely solely on the existence, modification time, and contents of the lock file itself. In this case, if the process currently locking the resource keeps it paststaleLockTime(),QLockFilewill steal the lock.Networked filesystems¶
It is unspecified whether the native file-locking is supported in networked environments: with some implementations, it is supported for all clients accessing the filesystem; for others the local system may support locking for its own processes but will not share the locking over the network; and for yet others there is no native locking even inside one host. Moreover, it is possible that some clients participate in networked locking and some others do not, for the same file. If locking is not supported across the network,
QLockFilewill observe the limitations described above for the absence of native locking.Additionally, if the lock file contains the identification of a different host,
QLockFilewill be unable to confirm the process holding a lock is still running, and will need to waitstaleLockTime()to recover from an unclean exit.Accessing different actual files through the same path¶
It is possible for two processes to have different views of the filesystem, causing an identical file path to be different files in the filesystem. In this case, the two
QLockFileobjects will likely succeed at creating the lock, but will not be mutually exclusive. This may cause conflicts if the resource the lock file is protecting is still shared between them.This situation is most often encountered with containers (see below), but is not exclusive to them.
Accesses not using the same protocol¶
QLockFilecannot interoperate with modifications to the lock file performed outside of the protocol implemented by this class. This includes removal of the lock file by other tools, such as tmpwatch and similar, but also some virus-scanning or similar tools.Clock skew¶
QLockFilerelies on the time stamp of the lock file being accurate. If the clock jumps forward,QLockFilemay conclude a lock file has become stale when it hasn’t, and vice-versa for jumping backwards.For this reason, it is recommended all systems keep network-synchronized time and perform this synchronization early in their boot process. This is particularly important for networked filesystems.
- class LockError¶
This enum describes the result of the last call to
lock()ortryLock().Constant
Description
QLockFile.LockError.NoError
The lock was acquired successfully.
QLockFile.LockError.LockFailedError
The lock could not be acquired because another process holds it.
QLockFile.LockError.PermissionError
The lock file could not be created, for lack of permissions in the parent directory.
QLockFile.LockError.UnknownError
Another error happened, for instance a full partition prevented writing out the lock file.
- __init__(fileName)¶
- Parameters:
fileName – str
Constructs a new lock file object. The object is created in an unlocked state. When calling
lock()ortryLock(), a lock file namedfileNamewill be created, if it doesn’t already exist.Returns the lock file error status.
If
tryLock()returnsfalse, this function can be called to find out the reason why the locking failed.- fileName()¶
- Return type:
str
Returns the file name of the lock file
- getLockInfo()¶
- Return type:
(int, str, str)
Retrieves information about the current owner of the lock file.
If
tryLock()returnsfalse, anderror()returnsLockFailedError, this function can be called to find out more information about the existing lock file:the PID of the application (returned in
pid)the
hostnameit’s running on (useful in case of networked filesystems),the name of the application which created it (returned in
appname),
Note that
tryLock()automatically deleted the file if there is no running application with this PID, soLockFailedErrorcan only happen if there is an application with this PID (it could be unrelated though).This can be used to inform users about the existing lock file and give them the choice to delete it. After removing the file using
removeStaleLockFile(), the application can calltryLock()again.This function returns
trueif the information could be successfully retrieved, false if the lock file doesn’t exist or doesn’t contain the expected data. This can happen if the lock file was deleted between the time wheretryLock()failed and the call to this function. Simply calltryLock()again if this happens.- isLocked()¶
- Return type:
bool
Returns
trueif the lock was acquired by thisQLockFileinstance, otherwise returnsfalse.- lock()¶
- Return type:
bool
Creates the lock file.
If another process (or another 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. This function will dead-lock when the file is locked recursively.
Returns
trueif the lock was acquired, false if it could not be acquired due to an unrecoverable error, such as no permissions in the parent directory.- removeStaleLockFile()¶
- Return type:
bool
Attempts to forcefully remove an existing lock file.
Calling this is not recommended when protecting a short-lived operation:
QLockFilealready takes care of removing lock files after they are older thanstaleLockTime().This method should only be called when protecting a resource for a long time, i.e. with
staleLockTime()(0), and aftertryLock()returnedLockFailedError, and the user agreed on removing the lock file.Returns
trueon success, false if the lock file couldn’t be removed. This happens on Windows, when the application owning the lock is still running.- setStaleLockTime(staleLockTime)¶
- Parameters:
staleLockTime – int
Sets
staleLockTimeto be the time in milliseconds after which a lock file is considered stale. 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 of
staleLockTimeis used bylock()andtryLock()in order to determine when an existing lock file is considered stale, i.e. left over by a crashed process. This is useful for the case where the PID got reused meanwhile, so one way to detect a stale lock file is by the fact that it has been around for a long time.This is an overloaded function, equivalent to calling:
setStaleLockTime(std::chrono::milliseconds{staleLockTime});
See also
- setStaleLockTime(value)
- Parameters:
value –
std::chrono::milliseconds
Sets the interval after which a lock file is considered stale to
staleLockTime. The default value is 30s.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 of
staleLockTime()is used bylock()andtryLock()in order to determine when an existing lock file is considered stale, i.e. left over by a crashed process. This is useful for the case where the PID got reused meanwhile, so one way to detect a stale lock file is by the fact that it has been around for a long time.Setting this value to 0 or negative will disable the verification of timestamps on lock files.
QLockFilewill still detect a stale lock if its contents show that the locking process is no longer running.See also
- staleLockTime()¶
- Return type:
int
Returns the time in milliseconds after which a lock file is considered stale.
See also
- staleLockTimeAsDuration()¶
- Return type:
std::chrono::milliseconds
Returns a std::chrono::milliseconds object which denotes the time after which a lock file is considered stale.
See also
- tryLock(timeout)¶
- Parameters:
timeout – int
- Return type:
bool
Attempts to create the lock file. This function returns
trueif the lock was obtained; otherwise it returnsfalse. If another process (or another thread) has created the lock file already, this function will wait for at mosttimeoutmilliseconds for the lock file to become available.Note: Passing a negative number as the
timeoutis equivalent to callinglock(), i.e. this function will wait forever until the lock file can be locked iftimeoutis 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, this function will always return false when attempting to lock the file recursively.
- tryLock([timeout=std.chrono.milliseconds.zero()])
- Parameters:
timeout –
std::chrono::milliseconds- Return type:
bool
Attempts to create the lock file. This function returns
trueif the lock was obtained; otherwise it returnsfalse. If another process (or another thread) has created the lock file already, this function will wait for at mosttimeoutfor the lock file to become available.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, this function will always return false when attempting to lock the file recursively.
- unlock()¶
Releases the lock, by deleting the lock file.
Calling unlock() without locking the file first, does nothing.