| 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 |