qlockfile.cpp

Absolute File Name:/home/qt/qt5_coco/qt5/qtbase/src/corelib/io/qlockfile.cpp
Source codeSwitch to Preprocessed file
LineSourceCount
1/****************************************************************************-
2**-
3** Copyright (C) 2013 David Faure <faure+bluesystems@kde.org>-
4** Copyright (C) 2016 The Qt Company Ltd.-
5** Contact: https://www.qt.io/licensing/-
6**-
7** This file is part of the QtCore module of the Qt Toolkit.-
8**-
9** $QT_BEGIN_LICENSE:LGPL$-
10** Commercial License Usage-
11** Licensees holding valid commercial Qt licenses may use this file in-
12** accordance with the commercial license agreement provided with the-
13** Software or, alternatively, in accordance with the terms contained in-
14** a written agreement between you and The Qt Company. For licensing terms-
15** and conditions see https://www.qt.io/terms-conditions. For further-
16** information use the contact form at https://www.qt.io/contact-us.-
17**-
18** GNU Lesser General Public License Usage-
19** Alternatively, this file may be used under the terms of the GNU Lesser-
20** General Public License version 3 as published by the Free Software-
21** Foundation and appearing in the file LICENSE.LGPL3 included in the-
22** packaging of this file. Please review the following information to-
23** ensure the GNU Lesser General Public License version 3 requirements-
24** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.-
25**-
26** GNU General Public License Usage-
27** Alternatively, this file may be used under the terms of the GNU-
28** General Public License version 2.0 or (at your option) the GNU General-
29** Public license version 3 or any later version approved by the KDE Free-
30** Qt Foundation. The licenses are as published by the Free Software-
31** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3-
32** included in the packaging of this file. Please review the following-
33** information to ensure the GNU General Public License requirements will-
34** be met: https://www.gnu.org/licenses/gpl-2.0.html and-
35** https://www.gnu.org/licenses/gpl-3.0.html.-
36**-
37** $QT_END_LICENSE$-
38**-
39****************************************************************************/-
40-
41#include "qlockfile.h"-
42#include "qlockfile_p.h"-
43-
44#include <QtCore/qthread.h>-
45#include <QtCore/qelapsedtimer.h>-
46#include <QtCore/qdatetime.h>-
47-
48QT_BEGIN_NAMESPACE-
49-
50/*!-
51 \class QLockFile-
52 \inmodule QtCore-
53 \brief The QLockFile class provides locking between processes using a file.-
54 \since 5.1-
55-
56 A lock file can be used to prevent multiple processes from accessing concurrently-
57 the same resource. For instance, a configuration file on disk, or a socket, a port,-
58 a region of shared memory...-
59-
60 Serialization is only guaranteed if all processes that access the shared resource-
61 use QLockFile, with the same file path.-
62-
63 QLockFile supports two use cases:-
64 to protect a resource for a short-term operation (e.g. verifying if a configuration-
65 file has changed before saving new settings), and for long-lived protection of a-
66 resource (e.g. a document opened by a user in an editor) for an indefinite amount of time.-
67-
68 When protecting for a short-term operation, it is acceptable to call lock() and wait-
69 until any running operation finishes.-
70 When protecting a resource over a long time, however, the application should always-
71 call setStaleLockTime(0) and then tryLock() with a short timeout, in order to-
72 warn the user that the resource is locked.-
73-
74 If the process holding the lock crashes, the lock file stays on disk and can prevent-
75 any other process from accessing the shared resource, ever. For this reason, QLockFile-
76 tries to detect such a "stale" lock file, based on the process ID written into the file.-
77 To cover the situation that the process ID got reused meanwhile, the current process name is-
78 compared to the name of the process that corresponds to the process ID from the lock file.-
79 If the process names differ, the lock file is considered stale.-
80 Additionally, the last modification time of the lock file (30s by default, for the use case of a-
81 short-lived operation) is taken into account.-
82 If the lock file is found to be stale, it will be deleted.-
83-
84 For the use case of protecting a resource over a long time, you should therefore call-
85 setStaleLockTime(0), and when tryLock() returns LockFailedError, inform the user-
86 that the document is locked, possibly using getLockInfo() for more details.-
87*/-
88-
89/*!-
90 \enum QLockFile::LockError-
91-
92 This enum describes the result of the last call to lock() or tryLock().-
93-
94 \value NoError The lock was acquired successfully.-
95 \value LockFailedError The lock could not be acquired because another process holds it.-
96 \value PermissionError The lock file could not be created, for lack of permissions-
97 in the parent directory.-
98 \value UnknownError Another error happened, for instance a full partition-
99 prevented writing out the lock file.-
100*/-
101-
102/*!-
103 Constructs a new lock file object.-
104 The object is created in an unlocked state.-
105 When calling lock() or tryLock(), a lock file named \a fileName will be created,-
106 if it doesn't already exist.-
107-
108 \sa lock(), unlock()-
109*/-
110QLockFile::QLockFile(const QString &fileName)-
111 : d_ptr(new QLockFilePrivate(fileName))-
112{-
113}
executed 4338 times by 33 tests: end of block
Executed by:
  • tst_QAbstractItemView
  • tst_QAccessibility
  • tst_QCalendarWidget
  • tst_QColorDialog
  • tst_QCommandLinkButton
  • tst_QCompleter
  • tst_QDateTimeEdit
  • tst_QErrorMessage
  • tst_QFileDialog2
  • tst_QFileIconProvider
  • tst_QFileSystemModel
  • tst_QFiledialog
  • tst_QGraphicsProxyWidget
  • tst_QIcon
  • tst_QLabel
  • tst_QLineEdit
  • tst_QLockFile
  • tst_QMessageBox
  • tst_QPlainTextEdit
  • tst_QPrinter
  • tst_QSettings
  • tst_QSidebar
  • tst_QStyle
  • tst_QStyleSheetStyle
  • tst_QSystemTrayIcon
  • ...
4338
114-
115/*!-
116 Destroys the lock file object.-
117 If the lock was acquired, this will release the lock, by deleting the lock file.-
118*/-
119QLockFile::~QLockFile()-
120{-
121 unlock();-
122}
executed 4338 times by 33 tests: end of block
Executed by:
  • tst_QAbstractItemView
  • tst_QAccessibility
  • tst_QCalendarWidget
  • tst_QColorDialog
  • tst_QCommandLinkButton
  • tst_QCompleter
  • tst_QDateTimeEdit
  • tst_QErrorMessage
  • tst_QFileDialog2
  • tst_QFileIconProvider
  • tst_QFileSystemModel
  • tst_QFiledialog
  • tst_QGraphicsProxyWidget
  • tst_QIcon
  • tst_QLabel
  • tst_QLineEdit
  • tst_QLockFile
  • tst_QMessageBox
  • tst_QPlainTextEdit
  • tst_QPrinter
  • tst_QSettings
  • tst_QSidebar
  • tst_QStyle
  • tst_QStyleSheetStyle
  • tst_QSystemTrayIcon
  • ...
4338
123-
124/*!-
125 Sets \a staleLockTime to be the time in milliseconds after which-
126 a lock file is considered stale.-
127 The default value is 30000, i.e. 30 seconds.-
128 If your application typically keeps the file locked for more than 30 seconds-
129 (for instance while saving megabytes of data for 2 minutes), you should set-
130 a bigger value using setStaleLockTime().-
131-
132 The value of \a staleLockTime is used by lock() and tryLock() in order-
133 to determine when an existing lock file is considered stale, i.e. left over-
134 by a crashed process. This is useful for the case where the PID got reused-
135 meanwhile, so one way to detect a stale lock file is by the fact that-
136 it has been around for a long time.-
137-
138 \sa staleLockTime()-
139*/-
140void QLockFile::setStaleLockTime(int staleLockTime)-
141{-
142 Q_D(QLockFile);-
143 d->staleLockTime = staleLockTime;-
144}
executed 1 time by 1 test: end of block
Executed by:
  • tst_QLockFile
1
145-
146/*!-
147 Returns the time in milliseconds after which-
148 a lock file is considered stale.-
149-
150 \sa setStaleLockTime()-
151*/-
152int QLockFile::staleLockTime() const-
153{-
154 Q_D(const QLockFile);-
155 return d->staleLockTime;
never executed: return d->staleLockTime;
0
156}-
157-
158/*!-
159 Returns \c true if the lock was acquired by this QLockFile instance,-
160 otherwise returns \c false.-
161-
162 \sa lock(), unlock(), tryLock()-
163*/-
164bool QLockFile::isLocked() const-
165{-
166 Q_D(const QLockFile);-
167 return d->isLocked;
executed 3 times by 2 tests: return d->isLocked;
Executed by:
  • tst_QLockFile
  • tst_qlockfile - unknown status
3
168}-
169-
170/*!-
171 Creates the lock file.-
172-
173 If another process (or another thread) has created the lock file already,-
174 this function will block until that process (or thread) releases it.-
175-
176 Calling this function multiple times on the same lock from the same-
177 thread without unlocking first is not allowed. This function will-
178 \e dead-lock when the file is locked recursively.-
179-
180 Returns \c true if the lock was acquired, false if it could not be acquired-
181 due to an unrecoverable error, such as no permissions in the parent directory.-
182-
183 \sa unlock(), tryLock()-
184*/-
185bool QLockFile::lock()-
186{-
187 return tryLock(-1);
executed 576 times by 8 tests: return tryLock(-1);
Executed by:
  • tst_QColorDialog
  • tst_QFileDialog2
  • tst_QFiledialog
  • tst_QGraphicsProxyWidget
  • tst_QLockFile
  • tst_QSettings
  • tst_languageChange
  • tst_qlockfile - unknown status
576
188}-
189-
190/*!-
191 Attempts to create the lock file. This function returns \c true if the-
192 lock was obtained; otherwise it returns \c false. If another process (or-
193 another thread) has created the lock file already, this function will-
194 wait for at most \a timeout milliseconds for the lock file to become-
195 available.-
196-
197 Note: Passing a negative number as the \a timeout is equivalent to-
198 calling lock(), i.e. this function will wait forever until the lock-
199 file can be locked if \a timeout is negative.-
200-
201 If the lock was obtained, it must be released with unlock()-
202 before another process (or thread) can successfully lock it.-
203-
204 Calling this function multiple times on the same lock from the same-
205 thread without unlocking first is not allowed, this function will-
206 \e always return false when attempting to lock the file recursively.-
207-
208 \sa lock(), unlock()-
209*/-
210bool QLockFile::tryLock(int timeout)-
211{-
212 Q_D(QLockFile);-
213 QElapsedTimer timer;-
214 if (timeout > 0)
timeout > 0Description
TRUEevaluated 4 times by 1 test
Evaluated by:
  • tst_QLockFile
FALSEevaluated 582 times by 8 tests
Evaluated by:
  • tst_QColorDialog
  • tst_QFileDialog2
  • tst_QFiledialog
  • tst_QGraphicsProxyWidget
  • tst_QLockFile
  • tst_QSettings
  • tst_languageChange
  • tst_qlockfile - unknown status
4-582
215 timer.start();
executed 4 times by 1 test: timer.start();
Executed by:
  • tst_QLockFile
4
216 int sleepTime = 100;-
217 forever {-
218 d->lockError = d->tryLock_sys();-
219 switch (d->lockError) {-
220 case NoError:
executed 580 times by 8 tests: case NoError:
Executed by:
  • tst_QColorDialog
  • tst_QFileDialog2
  • tst_QFiledialog
  • tst_QGraphicsProxyWidget
  • tst_QLockFile
  • tst_QSettings
  • tst_languageChange
  • tst_qlockfile - unknown status
580
221 d->isLocked = true;-
222 return true;
executed 580 times by 8 tests: return true;
Executed by:
  • tst_QColorDialog
  • tst_QFileDialog2
  • tst_QFiledialog
  • tst_QGraphicsProxyWidget
  • tst_QLockFile
  • tst_QSettings
  • tst_languageChange
  • tst_qlockfile - unknown status
580
223 case PermissionError:
executed 1 time by 1 test: case PermissionError:
Executed by:
  • tst_QLockFile
1
224 case UnknownError:
never executed: case UnknownError:
0
225 return false;
executed 1 time by 1 test: return false;
Executed by:
  • tst_QLockFile
1
226 case LockFailedError:
executed 17 times by 1 test: case LockFailedError:
Executed by:
  • tst_QLockFile
17
227 if (!d->isLocked && d->isApparentlyStale()) {
!d->isLockedDescription
TRUEevaluated 13 times by 1 test
Evaluated by:
  • tst_QLockFile
FALSEevaluated 4 times by 1 test
Evaluated by:
  • tst_QLockFile
d->isApparentlyStale()Description
TRUEevaluated 1 time by 1 test
Evaluated by:
  • tst_QLockFile
FALSEevaluated 12 times by 1 test
Evaluated by:
  • tst_QLockFile
1-13
228 // Stale lock from another thread/process-
229 // Ensure two processes don't remove it at the same time-
230 QLockFile rmlock(d->fileName + QLatin1String(".rmlock"));-
231 if (rmlock.tryLock()) {
rmlock.tryLock()Description
TRUEevaluated 1 time by 1 test
Evaluated by:
  • tst_QLockFile
FALSEnever evaluated
0-1
232 if (d->isApparentlyStale() && d->removeStaleLock())
d->isApparentlyStale()Description
TRUEevaluated 1 time by 1 test
Evaluated by:
  • tst_QLockFile
FALSEnever evaluated
d->removeStaleLock()Description
TRUEevaluated 1 time by 1 test
Evaluated by:
  • tst_QLockFile
FALSEnever evaluated
0-1
233 continue;
executed 1 time by 1 test: continue;
Executed by:
  • tst_QLockFile
1
234 }
never executed: end of block
0
235 }
never executed: end of block
0
236 break;
executed 16 times by 1 test: break;
Executed by:
  • tst_QLockFile
16
237 }-
238 if (timeout == 0 || (timeout > 0 && timer.hasExpired(timeout)))
timeout == 0Description
TRUEevaluated 3 times by 1 test
Evaluated by:
  • tst_QLockFile
FALSEevaluated 13 times by 1 test
Evaluated by:
  • tst_QLockFile
timeout > 0Description
TRUEevaluated 9 times by 1 test
Evaluated by:
  • tst_QLockFile
FALSEevaluated 4 times by 1 test
Evaluated by:
  • tst_QLockFile
timer.hasExpired(timeout)Description
TRUEevaluated 2 times by 1 test
Evaluated by:
  • tst_QLockFile
FALSEevaluated 7 times by 1 test
Evaluated by:
  • tst_QLockFile
2-13
239 return false;
executed 5 times by 1 test: return false;
Executed by:
  • tst_QLockFile
5
240 QThread::msleep(sleepTime);-
241 if (sleepTime < 5 * 1000)
sleepTime < 5 * 1000Description
TRUEevaluated 11 times by 1 test
Evaluated by:
  • tst_QLockFile
FALSEnever evaluated
0-11
242 sleepTime *= 2;
executed 11 times by 1 test: sleepTime *= 2;
Executed by:
  • tst_QLockFile
11
243 }
executed 11 times by 1 test: end of block
Executed by:
  • tst_QLockFile
11
244 // not reached-
245 return false;
never executed: return false;
0
246}-
247-
248/*!-
249 \fn void QLockFile::unlock()-
250 Releases the lock, by deleting the lock file.-
251-
252 Calling unlock() without locking the file first, does nothing.-
253-
254 \sa lock(), tryLock()-
255*/-
256-
257/*!-
258 Retrieves information about the current owner of the lock file.-
259-
260 If tryLock() returns \c false, and error() returns LockFailedError,-
261 this function can be called to find out more information about the existing-
262 lock file:-
263 \list-
264 \li the PID of the application (returned in \a pid)-
265 \li the \a hostname it's running on (useful in case of networked filesystems),-
266 \li the name of the application which created it (returned in \a appname),-
267 \endlist-
268-
269 Note that tryLock() automatically deleted the file if there is no-
270 running application with this PID, so LockFailedError can only happen if there is-
271 an application with this PID (it could be unrelated though).-
272-
273 This can be used to inform users about the existing lock file and give them-
274 the choice to delete it. After removing the file using removeStaleLockFile(),-
275 the application can call tryLock() again.-
276-
277 This function returns \c true if the information could be successfully retrieved, false-
278 if the lock file doesn't exist or doesn't contain the expected data.-
279 This can happen if the lock file was deleted between the time where tryLock() failed-
280 and the call to this function. Simply call tryLock() again if this happens.-
281*/-
282bool QLockFile::getLockInfo(qint64 *pid, QString *hostname, QString *appname) const-
283{-
284 Q_D(const QLockFile);-
285 return d->getLockInfo(pid, hostname, appname);
executed 1 time by 1 test: return d->getLockInfo(pid, hostname, appname);
Executed by:
  • tst_QLockFile
1
286}-
287-
288bool QLockFilePrivate::getLockInfo(qint64 *pid, QString *hostname, QString *appname) const-
289{-
290 QFile reader(fileName);-
291 if (!reader.open(QIODevice::ReadOnly))
!reader.open(Q...ice::ReadOnly)Description
TRUEnever evaluated
FALSEevaluated 15 times by 1 test
Evaluated by:
  • tst_QLockFile
0-15
292 return false;
never executed: return false;
0
293-
294 QByteArray pidLine = reader.readLine();-
295 pidLine.chop(1);-
296 if (pidLine.isEmpty())
pidLine.isEmpty()Description
TRUEevaluated 2 times by 1 test
Evaluated by:
  • tst_QLockFile
FALSEevaluated 13 times by 1 test
Evaluated by:
  • tst_QLockFile
2-13
297 return false;
executed 2 times by 1 test: return false;
Executed by:
  • tst_QLockFile
2
298 QByteArray appNameLine = reader.readLine();-
299 appNameLine.chop(1);-
300 QByteArray hostNameLine = reader.readLine();-
301 hostNameLine.chop(1);-
302-
303 qint64 thePid = pidLine.toLongLong();-
304 if (pid)
pidDescription
TRUEevaluated 13 times by 1 test
Evaluated by:
  • tst_QLockFile
FALSEnever evaluated
0-13
305 *pid = thePid;
executed 13 times by 1 test: *pid = thePid;
Executed by:
  • tst_QLockFile
13
306 if (appname)
appnameDescription
TRUEevaluated 13 times by 1 test
Evaluated by:
  • tst_QLockFile
FALSEnever evaluated
0-13
307 *appname = QString::fromUtf8(appNameLine);
executed 13 times by 1 test: *appname = QString::fromUtf8(appNameLine);
Executed by:
  • tst_QLockFile
13
308 if (hostname)
hostnameDescription
TRUEevaluated 13 times by 1 test
Evaluated by:
  • tst_QLockFile
FALSEnever evaluated
0-13
309 *hostname = QString::fromUtf8(hostNameLine);
executed 13 times by 1 test: *hostname = QString::fromUtf8(hostNameLine);
Executed by:
  • tst_QLockFile
13
310 return thePid > 0;
executed 13 times by 1 test: return thePid > 0;
Executed by:
  • tst_QLockFile
13
311}-
312-
313/*!-
314 Attempts to forcefully remove an existing lock file.-
315-
316 Calling this is not recommended when protecting a short-lived operation: QLockFile-
317 already takes care of removing lock files after they are older than staleLockTime().-
318-
319 This method should only be called when protecting a resource for a long time, i.e.-
320 with staleLockTime(0), and after tryLock() returned LockFailedError, and the user-
321 agreed on removing the lock file.-
322-
323 Returns \c true on success, false if the lock file couldn't be removed. This happens-
324 on Windows, when the application owning the lock is still running.-
325*/-
326bool QLockFile::removeStaleLockFile()-
327{-
328 Q_D(QLockFile);-
329 if (d->isLocked) {
d->isLockedDescription
TRUEnever evaluated
FALSEnever evaluated
0
330 qWarning("removeStaleLockFile can only be called when not holding the lock");-
331 return false;
never executed: return false;
0
332 }-
333 return d->removeStaleLock();
never executed: return d->removeStaleLock();
0
334}-
335-
336/*!-
337 Returns the lock file error status.-
338-
339 If tryLock() returns \c false, this function can be called to find out-
340 the reason why the locking failed.-
341*/-
342QLockFile::LockError QLockFile::error() const-
343{-
344 Q_D(const QLockFile);-
345 return d->lockError;
executed 14 times by 1 test: return d->lockError;
Executed by:
  • tst_QLockFile
14
346}-
347-
348QT_END_NAMESPACE-
Source codeSwitch to Preprocessed file

Generated by Squish Coco Non-Commercial 4.3.0-BETA-master-30-08-2018-4cb69e9