1 diff -Naur --exclude=CVS --exclude=.git qt-everywhere-opensource-src-5.5.1/qtbase/src/corelib/io/qlockfile_p.h qt-everywhere-opensource-src-5.5.1-patched/qtbase/src/corelib/io/qlockfile_p.h
2 --- qt-everywhere-opensource-src-5.5.1/qtbase/src/corelib/io/qlockfile_p.h 2015-10-13 07:35:31.000000000 +0300
3 +++ qt-everywhere-opensource-src-5.5.1-patched/qtbase/src/corelib/io/qlockfile_p.h 2016-01-29 11:53:10.000000000 +0300
5 static QString processNameByPid(qint64 pid);
8 - static int checkFcntlWorksAfterFlock();
9 + static int checkFcntlWorksAfterFlock(const QString &fn);
13 diff -Naur --exclude=CVS --exclude=.git qt-everywhere-opensource-src-5.5.1/qtbase/src/corelib/io/qlockfile_unix.cpp qt-everywhere-opensource-src-5.5.1-patched/qtbase/src/corelib/io/qlockfile_unix.cpp
14 --- qt-everywhere-opensource-src-5.5.1/qtbase/src/corelib/io/qlockfile_unix.cpp 2015-10-13 07:35:31.000000000 +0300
15 +++ qt-everywhere-opensource-src-5.5.1-patched/qtbase/src/corelib/io/qlockfile_unix.cpp 2016-01-29 11:53:10.000000000 +0300
17 #include "QtCore/qfileinfo.h"
18 #include "QtCore/qdebug.h"
19 #include "QtCore/qdatetime.h"
20 +#include "QtCore/qfileinfo.h"
21 +#include "QtCore/qcache.h"
22 +#include "QtCore/qglobalstatic.h"
23 +#include "QtCore/qmutex.h"
25 #include "private/qcore_unix_p.h" // qt_safe_open
26 #include "private/qabstractfileengine_p.h"
31 -int QLockFilePrivate::checkFcntlWorksAfterFlock()
32 +int QLockFilePrivate::checkFcntlWorksAfterFlock(const QString &fn)
34 #ifndef QT_NO_TEMPORARYFILE
35 - QTemporaryFile file;
36 + QTemporaryFile file(fn);
39 const int fd = file.d_func()->engine()->handle();
44 -static QBasicAtomicInt fcntlOK = Q_BASIC_ATOMIC_INITIALIZER(-1);
45 +// Cache the result of checkFcntlWorksAfterFlock for each directory a lock
46 +// file is created in because in some filesystems, like NFS, both locks
47 +// are the same. This does not take into account a filesystem changing.
48 +// QCache is set to hold a maximum of 10 entries, this is to avoid unbounded
49 +// growth, this is caching directories of files and it is assumed a low number
50 +// will be sufficient.
51 +typedef QCache<QString, bool> CacheType;
52 +Q_GLOBAL_STATIC_WITH_ARGS(CacheType, fcntlOK, (10));
53 +static QBasicMutex fcntlLock;
57 Checks that the OS isn't using POSIX locks to emulate flock().
60 -static bool fcntlWorksAfterFlock()
61 +static bool fcntlWorksAfterFlock(const QString &fn)
63 - int value = fcntlOK.load();
64 - if (Q_UNLIKELY(value == -1)) {
65 - value = QLockFilePrivate::checkFcntlWorksAfterFlock();
66 - fcntlOK.store(value);
67 + QMutexLocker lock(&fcntlLock);
68 + bool *worksPtr = fcntlOK->object(fn);
70 + worksPtr = new bool(QLockFilePrivate::checkFcntlWorksAfterFlock(fn));
71 + fcntlOK->insert(fn, worksPtr);
78 -static bool setNativeLocks(int fd)
79 +static bool setNativeLocks(const QString &fileName, int fd)
81 #if defined(LOCK_EX) && defined(LOCK_NB)
82 if (flock(fd, LOCK_EX | LOCK_NB) == -1) // other threads, and other processes on a local fs
84 flockData.l_start = 0;
85 flockData.l_len = 0; // 0 = entire file
86 flockData.l_pid = getpid();
87 - if (fcntlWorksAfterFlock() && fcntl(fd, F_SETLK, &flockData) == -1) // for networked filesystems
88 + if (fcntlWorksAfterFlock(QDir::cleanPath(QFileInfo(fileName).absolutePath()) + QString('/'))
89 + && fcntl(fd, F_SETLK, &flockData) == -1) { // for networked filesystems
98 // Ensure nobody else can delete the file while we have it
99 - if (!setNativeLocks(fd))
100 - qWarning() << "setNativeLocks failed:" << strerror(errno);
101 + if (!setNativeLocks(fileName, fd)) {
102 + const int errnoSaved = errno;
103 + qWarning() << "setNativeLocks failed:" << qt_error_string(errnoSaved);
106 if (qt_write_loop(fd, fileData.constData(), fileData.size()) < fileData.size()) {
109 const int fd = qt_safe_open(lockFileName.constData(), O_WRONLY, 0644);
110 if (fd < 0) // gone already?
112 - bool success = setNativeLocks(fd) && (::unlink(lockFileName) == 0);
113 + bool success = setNativeLocks(fileName, fd) && (::unlink(lockFileName) == 0);