diff options
author | Liang Qi <liang.qi@theqtcompany.com> | 2016-01-21 08:17:21 +0100 |
---|---|---|
committer | Liang Qi <liang.qi@theqtcompany.com> | 2016-01-21 08:17:21 +0100 |
commit | 158a3a4159bdc5a49caecd63e021dacbc06cf23c (patch) | |
tree | c3ed9aee6cabd46e5e8615b3815b92d32857c4da /src/corelib/io/qlockfile_unix.cpp | |
parent | 26ece94a68fb5ae680c5639716b06c4e1ae979a8 (diff) | |
parent | 7b2fb038ae4b8b9231ae989ad309b6eca107a858 (diff) |
Merge remote-tracking branch 'origin/5.6' into dev
Conflicts:
src/corelib/io/qiodevice_p.h
src/corelib/kernel/qvariant_p.h
src/corelib/tools/qsimd.cpp
src/gui/kernel/qguiapplication.cpp
tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp
Change-Id: I742a093cbb231b282b43e463ec67173e0d29f57a
Diffstat (limited to 'src/corelib/io/qlockfile_unix.cpp')
-rw-r--r-- | src/corelib/io/qlockfile_unix.cpp | 42 |
1 files changed, 29 insertions, 13 deletions
diff --git a/src/corelib/io/qlockfile_unix.cpp b/src/corelib/io/qlockfile_unix.cpp index 8bb94ee6c1..14ad103c4e 100644 --- a/src/corelib/io/qlockfile_unix.cpp +++ b/src/corelib/io/qlockfile_unix.cpp @@ -45,6 +45,10 @@ #include "QtCore/qfileinfo.h" #include "QtCore/qdebug.h" #include "QtCore/qdatetime.h" +#include "QtCore/qfileinfo.h" +#include "QtCore/qcache.h" +#include "QtCore/qglobalstatic.h" +#include "QtCore/qmutex.h" #include "private/qcore_unix_p.h" // qt_safe_open #include "private/qabstractfileengine_p.h" @@ -100,10 +104,10 @@ static qint64 qt_write_loop(int fd, const char *data, qint64 len) return pos; } -int QLockFilePrivate::checkFcntlWorksAfterFlock() +int QLockFilePrivate::checkFcntlWorksAfterFlock(const QString &fn) { #ifndef QT_NO_TEMPORARYFILE - QTemporaryFile file; + QTemporaryFile file(fn); if (!file.open()) return 0; const int fd = file.d_func()->engine()->handle(); @@ -125,24 +129,34 @@ int QLockFilePrivate::checkFcntlWorksAfterFlock() #endif } -static QBasicAtomicInt fcntlOK = Q_BASIC_ATOMIC_INITIALIZER(-1); +// Cache the result of checkFcntlWorksAfterFlock for each directory a lock +// file is created in because in some filesystems, like NFS, both locks +// are the same. This does not take into account a filesystem changing. +// QCache is set to hold a maximum of 10 entries, this is to avoid unbounded +// growth, this is caching directories of files and it is assumed a low number +// will be sufficient. +typedef QCache<QString, bool> CacheType; +Q_GLOBAL_STATIC_WITH_ARGS(CacheType, fcntlOK, (10)); +static QBasicMutex fcntlLock; /*! \internal Checks that the OS isn't using POSIX locks to emulate flock(). OS X is one of those. */ -static bool fcntlWorksAfterFlock() +static bool fcntlWorksAfterFlock(const QString &fn) { - int value = fcntlOK.load(); - if (Q_UNLIKELY(value == -1)) { - value = QLockFilePrivate::checkFcntlWorksAfterFlock(); - fcntlOK.store(value); + QMutexLocker lock(&fcntlLock); + bool *worksPtr = fcntlOK->object(fn); + if (!worksPtr) { + worksPtr = new bool(QLockFilePrivate::checkFcntlWorksAfterFlock(fn)); + fcntlOK->insert(fn, worksPtr); } - return value == 1; + + return *worksPtr; } -static bool setNativeLocks(int fd) +static bool setNativeLocks(const QString &fileName, int fd) { #if defined(LOCK_EX) && defined(LOCK_NB) if (flock(fd, LOCK_EX | LOCK_NB) == -1) // other threads, and other processes on a local fs @@ -154,8 +168,10 @@ static bool setNativeLocks(int fd) flockData.l_start = 0; flockData.l_len = 0; // 0 = entire file flockData.l_pid = getpid(); - if (fcntlWorksAfterFlock() && fcntl(fd, F_SETLK, &flockData) == -1) // for networked filesystems + if (fcntlWorksAfterFlock(QDir::cleanPath(QFileInfo(fileName).absolutePath()) + QString('/')) + && fcntl(fd, F_SETLK, &flockData) == -1) { // for networked filesystems return false; + } return true; } @@ -182,7 +198,7 @@ QLockFile::LockError QLockFilePrivate::tryLock_sys() } } // Ensure nobody else can delete the file while we have it - if (!setNativeLocks(fd)) { + if (!setNativeLocks(fileName, fd)) { const int errnoSaved = errno; qWarning() << "setNativeLocks failed:" << qt_error_string(errnoSaved); } @@ -213,7 +229,7 @@ bool QLockFilePrivate::removeStaleLock() const int fd = qt_safe_open(lockFileName.constData(), O_WRONLY, 0644); if (fd < 0) // gone already? return false; - bool success = setNativeLocks(fd) && (::unlink(lockFileName) == 0); + bool success = setNativeLocks(fileName, fd) && (::unlink(lockFileName) == 0); close(fd); return success; } |