From ef0129bb66768e6dea9e13ce650054e149a79f53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Martins?= Date: Mon, 25 Sep 2017 19:40:33 +0100 Subject: Don't read the statx struct in case of failure Change-Id: I62d98e4463003a1da8f28318d82635f6e0b2cc8c Reviewed-by: Thiago Macieira --- src/corelib/io/qfilesystemengine_unix.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src/corelib/io') diff --git a/src/corelib/io/qfilesystemengine_unix.cpp b/src/corelib/io/qfilesystemengine_unix.cpp index 9fb3855472..db8fe71326 100644 --- a/src/corelib/io/qfilesystemengine_unix.cpp +++ b/src/corelib/io/qfilesystemengine_unix.cpp @@ -412,8 +412,11 @@ bool QFileSystemEngine::fillMetaData(int fd, QFileSystemMetaData &data) int ret = qt_fstatx(fd, &statxBuffer); if (ret != -ENOSYS) { - data.fillFromStatxBuf(statxBuffer); - return ret == 0; + if (ret == 0) { + data.fillFromStatxBuf(statxBuffer); + return true; + } + return false; } if (QT_FSTAT(fd, &statBuffer) == 0) { -- cgit v1.2.3 From 8805fdb391d146e0d59b94930569799f936b1a5c Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Sun, 27 Aug 2017 11:23:39 +0300 Subject: QFileSystemEngine: Minor cleanup in unix Change-Id: I4a123484ea1f5e53af85a52e86d4a80cef1cd7bc Reviewed-by: Thiago Macieira --- src/corelib/io/qfilesystemengine_unix.cpp | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'src/corelib/io') diff --git a/src/corelib/io/qfilesystemengine_unix.cpp b/src/corelib/io/qfilesystemengine_unix.cpp index db8fe71326..1c07a0b7aa 100644 --- a/src/corelib/io/qfilesystemengine_unix.cpp +++ b/src/corelib/io/qfilesystemengine_unix.cpp @@ -638,13 +638,8 @@ QFileSystemEntry QFileSystemEngine::getLinkTarget(const QFileSystemEntry &link, } ret += QFile::decodeName(s); - if (!ret.startsWith(QLatin1Char('/'))) { - const QString linkPath = link.path(); - if (linkPath.startsWith(QLatin1Char('/'))) - ret.prepend(linkPath + QLatin1Char('/')); - else - ret.prepend(QDir::currentPath() + QLatin1Char('/') + linkPath + QLatin1Char('/')); - } + if (!ret.startsWith(QLatin1Char('/'))) + ret.prepend(absoluteName(link).path() + QLatin1Char('/')); ret = QDir::cleanPath(ret); if (ret.size() > 1 && ret.endsWith(QLatin1Char('/'))) ret.chop(1); -- cgit v1.2.3 From 1cb5943aee67cac18a28d64a59ae62f8459ba8a0 Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Sun, 27 Aug 2017 11:24:40 +0300 Subject: QFileSystemEngine: Remove unneeded test for relative symlink symLinkTarget should always return absolute path. Change-Id: Id0078924d2f0befdea91e652a6c7775707c1b3c8 Reviewed-by: Thiago Macieira --- src/corelib/io/qfilesystemengine.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'src/corelib/io') diff --git a/src/corelib/io/qfilesystemengine.cpp b/src/corelib/io/qfilesystemengine.cpp index 73a2e37a38..7abdf90bf5 100644 --- a/src/corelib/io/qfilesystemengine.cpp +++ b/src/corelib/io/qfilesystemengine.cpp @@ -86,8 +86,6 @@ QString QFileSystemEngine::slowCanonicalized(const QString &path) fi.setFile(prefix); if (fi.isSymLink()) { QString target = fi.symLinkTarget(); - if(QFileInfo(target).isRelative()) - target = fi.absolutePath() + slash + target; if (separatorPos != -1) { if (fi.isDir() && !target.endsWith(slash)) target.append(slash); -- cgit v1.2.3 From 7fd3cc3980a25bfbc9c0aca935c2afa90230374a Mon Sep 17 00:00:00 2001 From: Jake Petroules Date: Fri, 22 Sep 2017 11:20:54 -0700 Subject: Clean up OS version checks for Apple platforms Convert QSysInfo/QOperatingSystemVersion to __builtin_available where required or possible, or to QOperatingSystemVersion where __builtin_available cannot be used and is not needed (such as negated conditions, which are not supported by that construct). Change-Id: I83c0e7e777605b99ff4d24598bfcccf22126fdda Reviewed-by: Thiago Macieira --- src/corelib/io/qfilesystemengine_unix.cpp | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) (limited to 'src/corelib/io') diff --git a/src/corelib/io/qfilesystemengine_unix.cpp b/src/corelib/io/qfilesystemengine_unix.cpp index 1c07a0b7aa..52512c5e13 100644 --- a/src/corelib/io/qfilesystemengine_unix.cpp +++ b/src/corelib/io/qfilesystemengine_unix.cpp @@ -1232,11 +1232,7 @@ bool QFileSystemEngine::createLink(const QFileSystemEntry &source, const QFileSy bool QFileSystemEngine::copyFile(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error) { #if QT_DARWIN_PLATFORM_SDK_EQUAL_OR_ABOVE(101200, 100000, 100000, 30000) - const auto current = QOperatingSystemVersion::current(); - if (current >= QOperatingSystemVersion::MacOSSierra || - current >= QOperatingSystemVersion(QOperatingSystemVersion::IOS, 10) || - current >= QOperatingSystemVersion(QOperatingSystemVersion::TvOS, 10) || - current >= QOperatingSystemVersion(QOperatingSystemVersion::WatchOS, 3)) { + if (__builtin_available(macOS 10.12, iOS 10, tvOS 10, watchOS 3, *)) { if (::clonefile(source.nativeFilePath().constData(), target.nativeFilePath().constData(), 0) == 0) return true; @@ -1271,11 +1267,7 @@ bool QFileSystemEngine::renameFile(const QFileSystemEntry &source, const QFileSy } #endif #if defined(Q_OS_DARWIN) && defined(RENAME_EXCL) - const auto current = QOperatingSystemVersion::current(); - if (current >= QOperatingSystemVersion::MacOSSierra || - current >= QOperatingSystemVersion(QOperatingSystemVersion::IOS, 10) || - current >= QOperatingSystemVersion(QOperatingSystemVersion::TvOS, 10) || - current >= QOperatingSystemVersion(QOperatingSystemVersion::WatchOS, 3)) { + if (__builtin_available(macOS 10.12, iOS 10, tvOS 10, watchOS 3, *)) { if (renameatx_np(AT_FDCWD, srcPath, AT_FDCWD, tgtPath, RENAME_EXCL) == 0) return true; if (errno != ENOTSUP) { -- cgit v1.2.3 From 3399d79773fcd57dded2a184ee94936469538b4b Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 29 Sep 2017 21:20:08 -0700 Subject: QLockFile/Unix: drop the use of fcntl(F_SETLK) F_SETLK is bad. Explanation in the comment. And flock(2) does work with NFS on Linux, so let's just stick to that, which is simpler. We only use the file locks when we attempt to delete an apparently stale lock: that is, for a lock file that is at least staleLockTime old. Change-Id: I0b48fc8e90304e0dacc3fffd14e908c8c4c9d59b Reviewed-by: Oswald Buddenhagen Reviewed-by: David Faure --- src/corelib/io/qlockfile_p.h | 4 -- src/corelib/io/qlockfile_unix.cpp | 113 +++++++++++++++----------------------- 2 files changed, 44 insertions(+), 73 deletions(-) (limited to 'src/corelib/io') diff --git a/src/corelib/io/qlockfile_p.h b/src/corelib/io/qlockfile_p.h index 86a606ec00..a6f61b20f3 100644 --- a/src/corelib/io/qlockfile_p.h +++ b/src/corelib/io/qlockfile_p.h @@ -85,10 +85,6 @@ public: // used in dbusmenu Q_CORE_EXPORT static QString processNameByPid(qint64 pid); -#ifdef Q_OS_UNIX - static int checkFcntlWorksAfterFlock(const QString &fn); -#endif - QString fileName; #ifdef Q_OS_WIN Qt::HANDLE fileHandle; diff --git a/src/corelib/io/qlockfile_unix.cpp b/src/corelib/io/qlockfile_unix.cpp index 1ee8ce889c..30531d910e 100644 --- a/src/corelib/io/qlockfile_unix.cpp +++ b/src/corelib/io/qlockfile_unix.cpp @@ -94,79 +94,54 @@ static qint64 qt_write_loop(int fd, const char *data, qint64 len) return pos; } -int QLockFilePrivate::checkFcntlWorksAfterFlock(const QString &fn) -{ -#ifndef QT_NO_TEMPORARYFILE - QTemporaryFile file(fn); - if (!file.open()) - return 0; - const int fd = file.d_func()->engine()->handle(); -#if defined(LOCK_EX) && defined(LOCK_NB) - if (flock(fd, LOCK_EX | LOCK_NB) == -1) // other threads, and other processes on a local fs - return 0; -#endif - struct flock flockData; - flockData.l_type = F_WRLCK; - flockData.l_whence = SEEK_SET; - flockData.l_start = 0; - flockData.l_len = 0; // 0 = entire file - flockData.l_pid = getpid(); - if (fcntl(fd, F_SETLK, &flockData) == -1) // for networked filesystems - return 0; - return 1; -#else - Q_UNUSED(fn); - return 0; -#endif -} - -// 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 CacheType; -Q_GLOBAL_STATIC_WITH_ARGS(CacheType, fcntlOK, (10)); -static QBasicMutex fcntlLock; +/* + * Details about file locking on Unix. + * + * There are three types of advisory locks on Unix systems: + * 1) POSIX process-wide locks using fcntl(F_SETLK) + * 2) BSD flock(2) system call + * 3) Linux-specific file descriptor locks using fcntl(F_OFD_SETLK) + * There's also a mandatory locking feature by POSIX, which is deprecated on + * Linux and users are advised not to use it. + * + * The first problem is that the POSIX API is braindead. POSIX.1-2008 says: + * + * All locks associated with a file for a given process shall be removed when + * a file descriptor for that file is closed by that process or the process + * holding that file descriptor terminates. + * + * The Linux manpage is clearer: + * + * * If a process closes _any_ file descriptor referring to a file, then all + * of the process's locks on that file are released, regardless of the file + * descriptor(s) on which the locks were obtained. This is bad: [...] + * + * * The threads in a process share locks. In other words, a multithreaded + * program can't use record locking to ensure that threads don't + * simultaneously access the same region of a file. + * + * So in order to use POSIX locks, we'd need a global mutex that stays locked + * while the QLockFile is locked. For that reason, Qt does not use POSIX + * advisory locks anymore. + * + * The next problem is that POSIX leaves undefined the relationship between + * locks with fcntl(), flock() and lockf(). In some systems (like the BSDs), + * all three use the same record set, while on others (like Linux) the locks + * are independent, except if locking over NFS mounts, in which case they're + * actually the same. Therefore, it's a very bad idea to mix them in the same + * process. + * + * We therefore use only flock(2). + */ -/*! - \internal - Checks that the OS isn't using POSIX locks to emulate flock(). - \macos is one of those. -*/ -static bool fcntlWorksAfterFlock(const QString &fn) -{ - QMutexLocker lock(&fcntlLock); - if (fcntlOK.isDestroyed()) - return QLockFilePrivate::checkFcntlWorksAfterFlock(fn); - bool *worksPtr = fcntlOK->object(fn); - if (worksPtr) - return *worksPtr; - - const bool val = QLockFilePrivate::checkFcntlWorksAfterFlock(fn); - worksPtr = new bool(val); - fcntlOK->insert(fn, worksPtr); - - return val; -} - -static bool setNativeLocks(const QString &fileName, int fd) +static bool setNativeLocks(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 return false; +#else + Q_UNUSED(fd); #endif - struct flock flockData; - flockData.l_type = F_WRLCK; - flockData.l_whence = SEEK_SET; - flockData.l_start = 0; - flockData.l_len = 0; // 0 = entire file - flockData.l_pid = getpid(); - if (fcntlWorksAfterFlock(QDir::cleanPath(QFileInfo(fileName).absolutePath()) + QString('/')) - && fcntl(fd, F_SETLK, &flockData) == -1) { // for networked filesystems - return false; - } return true; } @@ -193,7 +168,7 @@ QLockFile::LockError QLockFilePrivate::tryLock_sys() } } // Ensure nobody else can delete the file while we have it - if (!setNativeLocks(fileName, fd)) { + if (!setNativeLocks(fd)) { const int errnoSaved = errno; qWarning() << "setNativeLocks failed:" << qt_error_string(errnoSaved); } @@ -224,7 +199,7 @@ bool QLockFilePrivate::removeStaleLock() const int fd = qt_safe_open(lockFileName.constData(), O_WRONLY, 0666); if (fd < 0) // gone already? return false; - bool success = setNativeLocks(fileName, fd) && (::unlink(lockFileName) == 0); + bool success = setNativeLocks(fd) && (::unlink(lockFileName) == 0); close(fd); return success; } -- cgit v1.2.3 From 4dca0cba304d18d19ec54df7dac719799279bc18 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 29 Sep 2017 23:59:03 -0700 Subject: QLockInfo: Centralize the management of the lock file's contents We duplicated both the creation of the contents and the check if the file was stale. Centralize everything in qlockfile.cpp. Change-Id: I0b48fc8e90304e0dacc3fffd14e91174af79841f Reviewed-by: Oswald Buddenhagen Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/io/qlockfile.cpp | 71 +++++++++++++++++++++++++++++++++------ src/corelib/io/qlockfile_p.h | 4 ++- src/corelib/io/qlockfile_unix.cpp | 42 +++++++++-------------- src/corelib/io/qlockfile_win.cpp | 60 ++++++++++++--------------------- 4 files changed, 100 insertions(+), 77 deletions(-) (limited to 'src/corelib/io') diff --git a/src/corelib/io/qlockfile.cpp b/src/corelib/io/qlockfile.cpp index 48317d07e0..197b1f80e5 100644 --- a/src/corelib/io/qlockfile.cpp +++ b/src/corelib/io/qlockfile.cpp @@ -2,6 +2,7 @@ ** ** Copyright (C) 2013 David Faure ** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2017 Intel Corporation. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -42,12 +43,34 @@ #include "qlockfile_p.h" #include +#include #include #include #include QT_BEGIN_NAMESPACE +namespace { +struct LockFileInfo +{ + qint64 pid; + QString appname; + QString hostname; +}; +} + +static bool getLockInfo_helper(const QString &fileName, LockFileInfo *info); + +static QString machineName() +{ +#ifdef Q_OS_WIN + // we don't use QSysInfo because it tries to do name resolution + return qEnvironmentVariable("COMPUTERNAME"); +#else + return QSysInfo::machineHostName(); +#endif +} + /*! \class QLockFile \inmodule QtCore @@ -291,10 +314,27 @@ bool QLockFile::tryLock(int timeout) bool QLockFile::getLockInfo(qint64 *pid, QString *hostname, QString *appname) const { Q_D(const QLockFile); - return d->getLockInfo(pid, hostname, appname); + LockFileInfo info; + if (!getLockInfo_helper(d->fileName, &info)) + return false; + if (pid) + *pid = info.pid; + if (hostname) + *hostname = info.hostname; + if (appname) + *appname = info.appname; + return true; } -bool QLockFilePrivate::getLockInfo(qint64 *pid, QString *hostname, QString *appname) const +QByteArray QLockFilePrivate::lockFileContents() const +{ + // Use operator% from the fast builder to avoid multiple memory allocations. + return QByteArray::number(QCoreApplication::applicationPid()) % '\n' + % QCoreApplication::applicationName().toUtf8() % '\n' + % machineName().toUtf8() % '\n'; +} + +static bool getLockInfo_helper(const QString &fileName, LockFileInfo *info) { QFile reader(fileName); if (!reader.open(QIODevice::ReadOnly)) @@ -309,14 +349,25 @@ bool QLockFilePrivate::getLockInfo(qint64 *pid, QString *hostname, QString *appn QByteArray hostNameLine = reader.readLine(); hostNameLine.chop(1); - qint64 thePid = pidLine.toLongLong(); - if (pid) - *pid = thePid; - if (appname) - *appname = QString::fromUtf8(appNameLine); - if (hostname) - *hostname = QString::fromUtf8(hostNameLine); - return thePid > 0; + bool ok; + info->appname = QString::fromUtf8(appNameLine); + info->hostname = QString::fromUtf8(hostNameLine); + info->pid = pidLine.toLongLong(&ok); + return ok && info->pid > 0; +} + +bool QLockFilePrivate::isApparentlyStale() const +{ + LockFileInfo info; + if (getLockInfo_helper(fileName, &info)) { + if (info.hostname.isEmpty() || info.hostname == machineName()) { + if (!isProcessRunning(info.pid, info.appname)) + return true; + } + } + + const qint64 age = QFileInfo(fileName).lastModified().msecsTo(QDateTime::currentDateTimeUtc()); + return staleLockTime > 0 && qAbs(age) > staleLockTime; } /*! diff --git a/src/corelib/io/qlockfile_p.h b/src/corelib/io/qlockfile_p.h index a6f61b20f3..b41dfb38ad 100644 --- a/src/corelib/io/qlockfile_p.h +++ b/src/corelib/io/qlockfile_p.h @@ -78,12 +78,14 @@ public: } QLockFile::LockError tryLock_sys(); bool removeStaleLock(); - bool getLockInfo(qint64 *pid, QString *hostname, QString *appname) const; + QByteArray lockFileContents() const; // Returns \c true if the lock belongs to dead PID, or is old. // The attempt to delete it will tell us if it was really stale or not, though. bool isApparentlyStale() const; + // used in dbusmenu Q_CORE_EXPORT static QString processNameByPid(qint64 pid); + static bool isProcessRunning(qint64 pid, const QString &appname); QString fileName; #ifdef Q_OS_WIN diff --git a/src/corelib/io/qlockfile_unix.cpp b/src/corelib/io/qlockfile_unix.cpp index 30531d910e..fc01f83e80 100644 --- a/src/corelib/io/qlockfile_unix.cpp +++ b/src/corelib/io/qlockfile_unix.cpp @@ -1,7 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2013 David Faure -** Copyright (C) 2016 Intel Corporation. +** Copyright (C) 2017 Intel Corporation. ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** @@ -42,7 +42,6 @@ #include "private/qlockfile_p.h" #include "QtCore/qtemporaryfile.h" -#include "QtCore/qcoreapplication.h" #include "QtCore/qfileinfo.h" #include "QtCore/qdebug.h" #include "QtCore/qdatetime.h" @@ -147,13 +146,6 @@ static bool setNativeLocks(int fd) QLockFile::LockError QLockFilePrivate::tryLock_sys() { - // Assemble data, to write in a single call to write - // (otherwise we'd have to check every write call) - // Use operator% from the fast builder to avoid multiple memory allocations. - QByteArray fileData = QByteArray::number(QCoreApplication::applicationPid()) % '\n' - % QCoreApplication::applicationName().toUtf8() % '\n' - % QSysInfo::machineHostName().toUtf8() % '\n'; - const QByteArray lockFileName = QFile::encodeName(fileName); const int fd = qt_safe_open(lockFileName.constData(), O_WRONLY | O_CREAT | O_EXCL, 0666); if (fd < 0) { @@ -173,6 +165,7 @@ QLockFile::LockError QLockFilePrivate::tryLock_sys() qWarning() << "setNativeLocks failed:" << qt_error_string(errnoSaved); } + QByteArray fileData = lockFileContents(); if (qt_write_loop(fd, fileData.constData(), fileData.size()) < fileData.size()) { qt_safe_close(fd); if (!QFile::remove(fileName)) @@ -204,26 +197,21 @@ bool QLockFilePrivate::removeStaleLock() return success; } -bool QLockFilePrivate::isApparentlyStale() const +bool QLockFilePrivate::isProcessRunning(qint64 pid, const QString &appname) { - qint64 pid; - QString hostname, appname; - if (getLockInfo(&pid, &hostname, &appname)) { - if (hostname.isEmpty() || hostname == QSysInfo::machineHostName()) { - if (::kill(pid, 0) == -1 && errno == ESRCH) - return true; // PID doesn't exist anymore - const QString processName = processNameByPid(pid); - if (!processName.isEmpty()) { - QFileInfo fi(appname); - if (fi.isSymLink()) - fi.setFile(fi.symLinkTarget()); - if (processName != fi.fileName()) - return true; // PID got reused by a different application. - } - } + if (::kill(pid, 0) == -1 && errno == ESRCH) + return false; // PID doesn't exist anymore + + const QString processName = processNameByPid(pid); + if (!processName.isEmpty()) { + QFileInfo fi(appname); + if (fi.isSymLink()) + fi.setFile(fi.symLinkTarget()); + if (processName != fi.fileName()) + return false; // PID got reused by a different application. } - const qint64 age = QFileInfo(fileName).lastModified().msecsTo(QDateTime::currentDateTime()); - return staleLockTime > 0 && qAbs(age) > staleLockTime; + + return true; } QString QLockFilePrivate::processNameByPid(qint64 pid) diff --git a/src/corelib/io/qlockfile_win.cpp b/src/corelib/io/qlockfile_win.cpp index 4b43181686..de64ec0432 100644 --- a/src/corelib/io/qlockfile_win.cpp +++ b/src/corelib/io/qlockfile_win.cpp @@ -2,6 +2,7 @@ ** ** Copyright (C) 2013 David Faure ** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2017 Intel Corporation. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -42,7 +43,6 @@ #include "private/qfilesystementry_p.h" #include -#include "QtCore/qcoreapplication.h" #include "QtCore/qfileinfo.h" #include "QtCore/qdatetime.h" #include "QtCore/qdebug.h" @@ -50,11 +50,6 @@ QT_BEGIN_NAMESPACE -static inline QByteArray localHostName() -{ - return qgetenv("COMPUTERNAME"); -} - static inline bool fileExists(const wchar_t *fileName) { WIN32_FILE_ATTRIBUTE_DATA data; @@ -107,15 +102,7 @@ QLockFile::LockError QLockFilePrivate::tryLock_sys() // We hold the lock, continue. fileHandle = fh; - // Assemble data, to write in a single call to write - // (otherwise we'd have to check every write call) - QByteArray fileData; - fileData += QByteArray::number(QCoreApplication::applicationPid()); - fileData += '\n'; - fileData += QCoreApplication::applicationName().toUtf8(); - fileData += '\n'; - fileData += localHostName(); - fileData += '\n'; + QByteArray fileData = lockFileContents(); DWORD bytesWritten = 0; QLockFile::LockError error = QLockFile::NoError; if (!WriteFile(fh, fileData.constData(), fileData.size(), &bytesWritten, NULL) || !FlushFileBuffers(fh)) @@ -129,38 +116,33 @@ bool QLockFilePrivate::removeStaleLock() return QFile::remove(fileName); } -bool QLockFilePrivate::isApparentlyStale() const +bool QLockFilePrivate::isProcessRunning(qint64 pid, const QString &appname) { - qint64 pid; - QString hostname, appname; - // On WinRT there seems to be no way of obtaining information about other // processes due to sandboxing #ifndef Q_OS_WINRT - if (getLockInfo(&pid, &hostname, &appname)) { - if (hostname.isEmpty() || hostname == QString::fromLocal8Bit(localHostName())) { - HANDLE procHandle = ::OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid); - if (!procHandle) - return true; - // We got a handle but check if process is still alive - DWORD exitCode = 0; - if (!::GetExitCodeProcess(procHandle, &exitCode)) - exitCode = 0; - ::CloseHandle(procHandle); - if (exitCode != STILL_ACTIVE) - return true; - const QString processName = processNameByPid(pid); - if (!processName.isEmpty() && processName != appname) - return true; // PID got reused by a different application. - } - } + HANDLE procHandle = ::OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid); + if (!procHandle) + return false; + + // We got a handle but check if process is still alive + DWORD exitCode = 0; + if (!::GetExitCodeProcess(procHandle, &exitCode)) + exitCode = 0; + ::CloseHandle(procHandle); + if (exitCode != STILL_ACTIVE) + return false; + + const QString processName = processNameByPid(pid); + if (!processName.isEmpty() && processName != appname) + return false; // PID got reused by a different application. + #else // !Q_OS_WINRT Q_UNUSED(pid); - Q_UNUSED(hostname); Q_UNUSED(appname); #endif // Q_OS_WINRT - const qint64 age = QFileInfo(fileName).lastModified().msecsTo(QDateTime::currentDateTime()); - return staleLockTime > 0 && qAbs(age) > staleLockTime; + + return true; } QString QLockFilePrivate::processNameByPid(qint64 pid) -- cgit v1.2.3 From db1027bc360cb86526d95dd0d7f36107a4d36b47 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Sat, 30 Sep 2017 00:20:53 -0700 Subject: QLockFile: don't use QCoreApplication::applicationName() That was stupid for two reasons. First, applicationName() can be changed by the user by calling QCoreApplication::setApplicationName(), so if that happens, we won't be able to properly identify a lock belonging to a given application because the name changed. Second, because applicationName() is not what we compare to. Instead, let's use processNameByPid() on both content creation and verification. [ChangeLog][QtCore][QLockFile] Fixed a bug that would cause QLockFile mis-identify valid lock files as stale if the application name was set with QCoreApplication::setApplicationName(). Change-Id: I0b48fc8e90304e0dacc3fffd14e912a5c98c87e7 Reviewed-by: Friedemann Kleint Reviewed-by: Oswald Buddenhagen Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/io/qlockfile.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/corelib/io') diff --git a/src/corelib/io/qlockfile.cpp b/src/corelib/io/qlockfile.cpp index 197b1f80e5..129cf01b63 100644 --- a/src/corelib/io/qlockfile.cpp +++ b/src/corelib/io/qlockfile.cpp @@ -330,7 +330,7 @@ QByteArray QLockFilePrivate::lockFileContents() const { // Use operator% from the fast builder to avoid multiple memory allocations. return QByteArray::number(QCoreApplication::applicationPid()) % '\n' - % QCoreApplication::applicationName().toUtf8() % '\n' + % processNameByPid(QCoreApplication::applicationPid()).toUtf8() % '\n' % machineName().toUtf8() % '\n'; } -- cgit v1.2.3