Absolute File Name: | /home/qt/qt5_coco/qt5/qtbase/src/corelib/io/qlockfile_unix.cpp |
Switch to Source code | Preprocessed file |
Line | Source | Count | ||||||
---|---|---|---|---|---|---|---|---|
1 | - | |||||||
2 | - | |||||||
3 | - | |||||||
4 | - | |||||||
5 | - | |||||||
6 | - | |||||||
7 | static QByteArray localHostName() | - | ||||||
8 | { | - | ||||||
9 | QByteArray hostName(512, Qt::Uninitialized); | - | ||||||
10 | if (gethostname(hostName.data(), hostName.size()) == -1) | - | ||||||
11 | return QByteArray(); | - | ||||||
12 | hostName.truncate(strlen(hostName.data())); | - | ||||||
13 | return hostName; | - | ||||||
14 | } | - | ||||||
15 | - | |||||||
16 | - | |||||||
17 | static qint64 qt_write_loop(int fd, const char *data, qint64 len) | - | ||||||
18 | { | - | ||||||
19 | qint64 pos = 0; | - | ||||||
20 | while (pos < len) { | - | ||||||
21 | const qint64 ret = qt_safe_write(fd, data + pos, len - pos); | - | ||||||
22 | if (ret == -1) | - | ||||||
23 | return pos; | - | ||||||
24 | pos += ret; | - | ||||||
25 | } | - | ||||||
26 | return pos; | - | ||||||
27 | } | - | ||||||
28 | - | |||||||
29 | int QLockFilePrivate::checkFcntlWorksAfterFlock(const QString &fn) | - | ||||||
30 | { | - | ||||||
31 | - | |||||||
32 | QTemporaryFile file(fn); | - | ||||||
33 | if (!file.open()) | - | ||||||
34 | return 0; | - | ||||||
35 | const int fd = file.d_func()->engine()->handle(); | - | ||||||
36 | - | |||||||
37 | if (flock(fd, 2 | 4) == -1) | - | ||||||
38 | return 0; | - | ||||||
39 | - | |||||||
40 | struct flock flockData; | - | ||||||
41 | flockData.l_type = 1; | - | ||||||
42 | flockData.l_whence = 0; | - | ||||||
43 | flockData.l_start = 0; | - | ||||||
44 | flockData.l_len = 0; | - | ||||||
45 | flockData.l_pid = getpid(); | - | ||||||
46 | if (fcntl(fd, 6, &flockData) == -1) | - | ||||||
47 | return 0; | - | ||||||
48 | return 1; | - | ||||||
49 | - | |||||||
50 | - | |||||||
51 | - | |||||||
52 | } | - | ||||||
53 | - | |||||||
54 | - | |||||||
55 | - | |||||||
56 | - | |||||||
57 | - | |||||||
58 | - | |||||||
59 | - | |||||||
60 | typedef QCache<QString, bool> CacheType; | - | ||||||
61 | namespace { namespace Q_QGS_fcntlOK { typedef CacheType Type; QBasicAtomicInt guard = { QtGlobalStatic::Uninitialized }; __attribute__((visibility("hidden"))) inline Type *innerFunction() { struct HolderBase { ~HolderBase() noexcept { if (guard.load() == QtGlobalStatic::Initialized) guard.store(QtGlobalStatic::Destroyed); } }; static struct Holder : public HolderBase { Type value; Holder() noexcept(noexcept(Type (10))) : value (10) { guard.store(QtGlobalStatic::Initialized); } } holder; return &holder.value; } } } static QGlobalStatic<CacheType, Q_QGS_fcntlOK::innerFunction, Q_QGS_fcntlOK::guard> fcntlOK;; | - | ||||||
62 | static QBasicMutex fcntlLock; | - | ||||||
63 | - | |||||||
64 | - | |||||||
65 | - | |||||||
66 | - | |||||||
67 | - | |||||||
68 | - | |||||||
69 | static bool fcntlWorksAfterFlock(const QString &fn) | - | ||||||
70 | { | - | ||||||
71 | QMutexLocker lock(&fcntlLock); | - | ||||||
72 | if (fcntlOK.isDestroyed()) | - | ||||||
73 | return QLockFilePrivate::checkFcntlWorksAfterFlock(fn); | - | ||||||
74 | bool *worksPtr = fcntlOK->object(fn); | - | ||||||
75 | if (worksPtr) | - | ||||||
76 | return *worksPtr; | - | ||||||
77 | - | |||||||
78 | const bool val = QLockFilePrivate::checkFcntlWorksAfterFlock(fn); | - | ||||||
79 | worksPtr = new bool(val); | - | ||||||
80 | fcntlOK->insert(fn, worksPtr); | - | ||||||
81 | - | |||||||
82 | return val; | - | ||||||
83 | } | - | ||||||
84 | - | |||||||
85 | static bool setNativeLocks(const QString &fileName, int fd) | - | ||||||
86 | { | - | ||||||
87 | - | |||||||
88 | if (flock(fd, 2 | 4) == -1) | - | ||||||
89 | return false; | - | ||||||
90 | - | |||||||
91 | struct flock flockData; | - | ||||||
92 | flockData.l_type = 1; | - | ||||||
93 | flockData.l_whence = 0; | - | ||||||
94 | flockData.l_start = 0; | - | ||||||
95 | flockData.l_len = 0; | - | ||||||
96 | flockData.l_pid = getpid(); | - | ||||||
97 | if (fcntlWorksAfterFlock(QDir::cleanPath(QFileInfo(fileName).absolutePath()) + QString('/')) | - | ||||||
98 | && fcntl(fd, 6, &flockData) == -1) { | - | ||||||
99 | return false; | - | ||||||
100 | } | - | ||||||
101 | return true; | - | ||||||
102 | } | - | ||||||
103 | - | |||||||
104 | QLockFile::LockError QLockFilePrivate::tryLock_sys() | - | ||||||
105 | { | - | ||||||
106 | - | |||||||
107 | - | |||||||
108 | - | |||||||
109 | QByteArray fileData = QByteArray::number(QCoreApplication::applicationPid()) % '\n' | - | ||||||
110 | % QCoreApplication::applicationName().toUtf8() % '\n' | - | ||||||
111 | % localHostName() % '\n'; | - | ||||||
112 | - | |||||||
113 | const QByteArray lockFileName = QFile::encodeName(fileName); | - | ||||||
114 | const int fd = qt_safe_open(lockFileName.constData(), 01 | 0100 | 0200, 0666); | - | ||||||
115 | if (fd < 0) { | - | ||||||
116 | switch ((*__errno_location ())) { | - | ||||||
117 | case 17: | - | ||||||
118 | return QLockFile::LockFailedError; | - | ||||||
119 | case 13: | - | ||||||
120 | case 30: | - | ||||||
121 | return QLockFile::PermissionError; | - | ||||||
122 | default: | - | ||||||
123 | return QLockFile::UnknownError; | - | ||||||
124 | } | - | ||||||
125 | } | - | ||||||
126 | - | |||||||
127 | if (!setNativeLocks(fileName, fd)) { | - | ||||||
128 | const int errnoSaved = (*__errno_location ()); | - | ||||||
129 | QMessageLogger(__FILE__, 194206, __PRETTY_FUNCTION__).warning() << "setNativeLocks failed:" << qt_error_string(errnoSaved); | - | ||||||
130 | } | - | ||||||
131 | - | |||||||
132 | if (qt_write_loop(fd, fileData.constData(), fileData.size()) < fileData.size()) { | - | ||||||
133 | close(fd); | - | ||||||
134 | if (!QFile::remove(fileName)) | - | ||||||
135 | QMessageLogger(__FILE__, 200212, __PRETTY_FUNCTION__).warning("QLockFile: Could not remove our own lock file %s.", QString(fileName).toLocal8Bit().constData()); | - | ||||||
136 | return QLockFile::UnknownError; | - | ||||||
137 | } | - | ||||||
138 | - | |||||||
139 | - | |||||||
140 | fileHandle = fd; | - | ||||||
141 | - | |||||||
142 | - | |||||||
143 | - | |||||||
144 | fdatasync(fileHandle); | - | ||||||
145 | - | |||||||
146 | - | |||||||
147 | - | |||||||
148 | - | |||||||
149 | return QLockFile::NoError; | - | ||||||
150 | } | - | ||||||
151 | - | |||||||
152 | bool QLockFilePrivate::removeStaleLock() | - | ||||||
153 | { | - | ||||||
154 | const QByteArray lockFileName = QFile::encodeName(fileName); | - | ||||||
155 | const int fd = qt_safe_open(lockFileName.constData(), 01, 0666); | - | ||||||
156 | if (fd < 0) | - | ||||||
157 | return false; | - | ||||||
158 | bool success = setNativeLocks(fileName, fd) && (::unlink(lockFileName) == 0); | - | ||||||
159 | close(fd); | - | ||||||
160 | return success; | - | ||||||
161 | } | - | ||||||
162 | - | |||||||
163 | bool QLockFilePrivate::isApparentlyStale() const | - | ||||||
164 | { | - | ||||||
165 | qint64 pid; | - | ||||||
166 | QString hostname, appname; | - | ||||||
167 | if (getLockInfo(&pid, &hostname, &appname)) { | - | ||||||
168 | if (hostname.isEmpty() || hostname == QString::fromLocal8Bit(localHostName())) { | - | ||||||
169 | if (::kill(pid, 0) == -1 && (*__errno_location ()) == 3) | - | ||||||
170 | return true; | - | ||||||
171 | const QString processName = processNameByPid(pid); | - | ||||||
172 | if (!processName.isEmpty()) { | - | ||||||
173 | QFileInfo fi(appname); | - | ||||||
174 | if (fi.isSymLink()) | - | ||||||
175 | fi.setFile(fi.symLinkTarget()); | - | ||||||
176 | if (processName != fi.fileName()) | - | ||||||
177 | return true; | - | ||||||
178 | } | - | ||||||
179 | } | - | ||||||
180 | } | - | ||||||
181 | const qint64 age = QFileInfo(fileName).lastModified().msecsTo(QDateTime::currentDateTime()); | - | ||||||
182 | return staleLockTime > 0 && age > staleLockTime; | - | ||||||
183 | } | - | ||||||
184 | - | |||||||
185 | QString QLockFilePrivate::processNameByPid(qint64 pid) | - | ||||||
186 | { | - | ||||||
187 | - | |||||||
188 | - | |||||||
189 | - | |||||||
190 | - | |||||||
191 | - | |||||||
192 | if (!QFile::exists(([]() -> QString { enum { Size = sizeof(u"" "/proc/version")/2 - 1 }; static const QStaticStringData<Size> qstring_literal = { { { { -1 } }, Size, 0, 0, sizeof(QStringData) }, u"" "/proc/version" }; QStringDataPtr holder = { qstring_literal.data_ptr() }; const QString qstring_literal_temp(holder); return qstring_literal_temp; }()))
| 0-12 | ||||||
193 | return never executed: QString();return QString(); never executed: return QString(); | 0 | ||||||
194 | char exePath[64]; | - | ||||||
195 | char buf[4096 + 1]; | - | ||||||
196 | sprintf(exePath, "/proc/%lld/exe", pid); | - | ||||||
197 | size_t len = (size_t)readlink(exePath, buf, sizeof(buf)); | - | ||||||
198 | if (len >= sizeof(buf)
| 0-12 | ||||||
199 | - | |||||||
200 | return never executed: ([]() -> QString { enum { Size = sizeof(u"" "/ERROR/")/2 - 1 }; static const QStaticStringData<Size> qstring_literal = { { { { -1 } }, Size, 0, 0, sizeof(QStringData) }, u"" "/ERROR/" }; QStringDataPtr holder = { qstring_literal.data_ptr() }; const QString qstring_literal_temp(holder); returnreturn ([]() -> QString { enum { Size = sizeof(u"" "/ERROR/")/2 - 1 }; static const QStaticStringData<Size> qstring_literal = { { { { -1 } }, Size, 0, 0, sizeof(QStringData) }, u"" "/ERROR/" }; QStringDataPtr holder = { qstring_literal.data_ptr() }; const QString qstring_literal_temp(holder); return qstring_literal_temp; }()); never executed: qstring_literal_temp;return qstring_literal_temp; never executed: }());return qstring_literal_temp; never executed: return ([]() -> QString { enum { Size = sizeof(u"" "/ERROR/")/2 - 1 }; static const QStaticStringData<Size> qstring_literal = { { { { -1 } }, Size, 0, 0, sizeof(QStringData) }, u"" "/ERROR/" }; QStringDataPtr holder = { qstring_literal.data_ptr() }; const QString qstring_literal_temp(holder); return qstring_literal_temp; }()); | 0 | ||||||
201 | } | - | ||||||
202 | buf[len] = 0; | - | ||||||
203 | return executed 12 times by 1 test: QFileInfo(QFile::decodeName(buf)).fileName();return QFileInfo(QFile::decodeName(buf)).fileName(); Executed by:
executed 12 times by 1 test: return QFileInfo(QFile::decodeName(buf)).fileName(); Executed by:
| 12 | ||||||
204 | } | - | ||||||
205 | - | |||||||
206 | void QLockFile::unlock() | - | ||||||
207 | { | - | ||||||
208 | QLockFilePrivate * const d = d_func(); | - | ||||||
209 | if (!d->isLocked) | - | ||||||
210 | return; | - | ||||||
211 | close(d->fileHandle); | - | ||||||
212 | d->fileHandle = -1; | - | ||||||
213 | if (!QFile::remove(d->fileName)) { | - | ||||||
214 | QMessageLogger(__FILE__, 311328, __PRETTY_FUNCTION__).warning() << "Could not remove our own lock file" << d->fileName << "maybe permissions changed meanwhile?"; | - | ||||||
215 | - | |||||||
216 | } | - | ||||||
217 | d->lockError = QLockFile::NoError; | - | ||||||
218 | d->isLocked = false; | - | ||||||
219 | } | - | ||||||
220 | - | |||||||
221 | - | |||||||
Switch to Source code | Preprocessed file |