From 637fdcc5ba6e20ff1ffe29dde7ca6c56f66f25b7 Mon Sep 17 00:00:00 2001 From: Alessandro Portale Date: Thu, 24 Aug 2023 17:03:13 +0000 Subject: Revert "App: Replace QtLockedFile usage with QLockFile" This reverts commit 1fca05959f0a321943d803941c2fcdb7f6f0258d. Reason for revert: Portale +2'ed under the assumption that this goes into the master branch. This year old issue should definitely be fixed, but typically not that urgently in a .3 patch release Let's revert this and move it on master, please. I take the blame for the messy git history. Change-Id: I8ae5a5e8e89ce38e7fe663b09cb6c2c3ab520ab0 Reviewed-by: Cristian Adam --- src/app/app.qbs | 18 +++ src/shared/CMakeLists.txt | 1 + src/shared/qtlockedfile/CMakeLists.txt | 17 +++ src/shared/qtlockedfile/README.txt | 10 ++ src/shared/qtlockedfile/namespace.patch | 70 +++++++++ src/shared/qtlockedfile/qtlockedfile.cpp | 132 ++++++++++++++++ src/shared/qtlockedfile/qtlockedfile.h | 48 ++++++ src/shared/qtlockedfile/qtlockedfile_unix.cpp | 82 ++++++++++ src/shared/qtlockedfile/qtlockedfile_win.cpp | 170 +++++++++++++++++++++ src/shared/qtsingleapplication/CMakeLists.txt | 2 +- src/shared/qtsingleapplication/qtlocalpeer.cpp | 7 +- src/shared/qtsingleapplication/qtlocalpeer.h | 9 +- .../qtsingleapplication/qtsingleapplication.cpp | 15 +- 13 files changed, 566 insertions(+), 15 deletions(-) create mode 100644 src/shared/qtlockedfile/CMakeLists.txt create mode 100644 src/shared/qtlockedfile/README.txt create mode 100644 src/shared/qtlockedfile/namespace.patch create mode 100644 src/shared/qtlockedfile/qtlockedfile.cpp create mode 100644 src/shared/qtlockedfile/qtlockedfile.h create mode 100644 src/shared/qtlockedfile/qtlockedfile_unix.cpp create mode 100644 src/shared/qtlockedfile/qtlockedfile_win.cpp diff --git a/src/app/app.qbs b/src/app/app.qbs index f684909bec..a0b30ae2ae 100644 --- a/src/app/app.qbs +++ b/src/app/app.qbs @@ -40,6 +40,7 @@ QtcProduct { : ["$ORIGIN/../" + qtc.libDirName + "/qtcreator"] cpp.includePaths: [ project.sharedSourcesDir + "/qtsingleapplication", + project.sharedSourcesDir + "/qtlockedfile", ] cpp.frameworks: base.concat(qbs.targetOS.contains("macos") ? ["Foundation"] : []) @@ -57,6 +58,7 @@ QtcProduct { "../shared/qtsingleapplication/qtsingleapplication.cpp", "../shared/qtsingleapplication/qtlocalpeer.h", "../shared/qtsingleapplication/qtlocalpeer.cpp", + "../shared/qtlockedfile/qtlockedfile.cpp", "../tools/qtcreatorcrashhandler/crashhandlersetup.cpp", "../tools/qtcreatorcrashhandler/crashhandlersetup.h" ] @@ -82,6 +84,22 @@ QtcProduct { qbs.installDir: "bin" } + Group { + name: "QtLockedFile_unix" + condition: qbs.targetOS.contains("unix") + files: [ + "../shared/qtlockedfile/qtlockedfile_unix.cpp" + ] + } + + Group { + name: "QtLockedFile_win" + condition: qbs.targetOS.contains("windows") + files: [ + "../shared/qtlockedfile/qtlockedfile_win.cpp" + ] + } + Group { name: "main_macos" condition: qbs.targetOS.contains("macos") diff --git a/src/shared/CMakeLists.txt b/src/shared/CMakeLists.txt index e6210760d2..93409b0bf4 100644 --- a/src/shared/CMakeLists.txt +++ b/src/shared/CMakeLists.txt @@ -1,6 +1,7 @@ add_subdirectory(designerintegrationv2) add_subdirectory(proparser) add_subdirectory(qtsingleapplication) +add_subdirectory(qtlockedfile) add_subdirectory(help) add_subdirectory(registryaccess) diff --git a/src/shared/qtlockedfile/CMakeLists.txt b/src/shared/qtlockedfile/CMakeLists.txt new file mode 100644 index 0000000000..f7f8a1c666 --- /dev/null +++ b/src/shared/qtlockedfile/CMakeLists.txt @@ -0,0 +1,17 @@ +if (WIN32) + set(OS_SOURCES qtlockedfile_win.cpp) +else() + set(OS_SOURCES qtlockedfile_unix.cpp) +endif() + +add_library(shared_qtlockedfile STATIC ${OS_SOURCES} qtlockedfile.cpp qtlockedfile.h) +target_link_libraries(shared_qtlockedfile Qt::Core) +target_include_directories(shared_qtlockedfile PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}") +if (WIN32) + target_compile_definitions(shared_qtlockedfile PRIVATE + "QT_QTLOCKEDFILE_EXPORT=__declspec(dllexport)" _UNICODE UNICODE) +endif() + +if (WITH_SANITIZE) + qtc_enable_sanitize(shared_qtlockedfile ${SANITIZE_FLAGS}) +endif() diff --git a/src/shared/qtlockedfile/README.txt b/src/shared/qtlockedfile/README.txt new file mode 100644 index 0000000000..6fcf2fd295 --- /dev/null +++ b/src/shared/qtlockedfile/README.txt @@ -0,0 +1,10 @@ +This is the src directory of the QtLockedFile +solution integrated over from addons/main/utils/qtlockedfile/src . + +namespace.patch was applied to introduce the SharedTools namespace. + +It is required by the QtSingleApplication solution. + +History: + +16.05.2008 Integrated diff --git a/src/shared/qtlockedfile/namespace.patch b/src/shared/qtlockedfile/namespace.patch new file mode 100644 index 0000000000..301cae8cff --- /dev/null +++ b/src/shared/qtlockedfile/namespace.patch @@ -0,0 +1,70 @@ + +--- qtlockedfile.cpp 1970-01-01 01:00:00.000000000 ++++ qtlockedfile.cpp 2008/05/16 10:51:19.000000000 +@@ -1,5 +1,7 @@ + #include "qtlockedfile.h" + ++namespace SharedTools { ++ + /*! + \class QtLockedFile + +@@ -123,3 +125,5 @@ + + Destroys the \e QtLockedFile object. If any locks were held, they are released. + */ ++ ++} + +--- qtlockedfile.h 1970-01-01 01:00:00.000000000 ++++ qtlockedfile.h 2008/05/16 10:51:19.000000000 +@@ -19,6 +19,8 @@ + # define QT_QTLOCKEDFILE_EXPORT + #endif + ++namespace SharedTools { ++ + class QT_QTLOCKEDFILE_EXPORT QtLockedFile : public QFile + { + public: +@@ -41,4 +43,6 @@ + LockMode m_lock_mode; + }; + ++} ++ + #endif + +--- qtlockedfile_unix.cpp 1970-01-01 01:00:00.000000000 ++++ qtlockedfile_unix.cpp 2008/05/16 10:51:19.000000000 +@@ -5,6 +5,8 @@ + + #include "qtlockedfile.h" + ++namespace SharedTools { ++ + bool QtLockedFile::lock(LockMode mode, bool block) + { + if (!isOpen()) { +@@ -73,3 +75,4 @@ + unlock(); + } + ++} + +--- qtlockedfile_win.cpp 1970-01-01 01:00:00.000000000 ++++ qtlockedfile_win.cpp 2008/05/16 10:51:19.000000000 +@@ -2,6 +2,8 @@ + #include + #include + ++namespace SharedTools { ++ + #define SEMAPHORE_PREFIX "QtLockedFile semaphore " + #define MUTEX_PREFIX "QtLockedFile mutex " + #define SEMAPHORE_MAX 100 +@@ -168,3 +170,4 @@ + } + } + ++} diff --git a/src/shared/qtlockedfile/qtlockedfile.cpp b/src/shared/qtlockedfile/qtlockedfile.cpp new file mode 100644 index 0000000000..a14c7e14b0 --- /dev/null +++ b/src/shared/qtlockedfile/qtlockedfile.cpp @@ -0,0 +1,132 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#include "qtlockedfile.h" + +namespace SharedTools { + +/*! + \class QtLockedFile + + \brief The QtLockedFile class extends QFile with advisory locking functions. + + A file may be locked in read or write mode. Multiple instances of + \e QtLockedFile, created in multiple processes running on the same + machine, may have a file locked in read mode. Exactly one instance + may have it locked in write mode. A read and a write lock cannot + exist simultaneously on the same file. + + The file locks are advisory. This means that nothing prevents + another process from manipulating a locked file using QFile or + file system functions offered by the OS. Serialization is only + guaranteed if all processes that access the file use + QtLockedFile. Also, while holding a lock on a file, a process + must not open the same file again (through any API), or locks + can be unexpectedly lost. + + The lock provided by an instance of \e QtLockedFile is released + whenever the program terminates. This is true even when the + program crashes and no destructors are called. +*/ + +/*! \enum QtLockedFile::LockMode + + This enum describes the available lock modes. + + \value ReadLock A read lock. + \value WriteLock A write lock. + \value NoLock Neither a read lock nor a write lock. +*/ + +/*! + Constructs an unlocked \e QtLockedFile object. This constructor behaves in the same way + as \e QFile::QFile(). + + \sa QFile::QFile() +*/ +QtLockedFile::QtLockedFile() + : QFile() +{ +#ifdef Q_OS_WIN + m_semaphore_hnd = 0; + m_mutex_hnd = 0; +#endif + m_lock_mode = NoLock; +} + +/*! + Constructs an unlocked QtLockedFile object with file \a name. This constructor behaves in + the same way as \e QFile::QFile(const QString&). + + \sa QFile::QFile() +*/ +QtLockedFile::QtLockedFile(const QString &name) + : QFile(name) +{ +#ifdef Q_OS_WIN + m_semaphore_hnd = 0; + m_mutex_hnd = 0; +#endif + m_lock_mode = NoLock; +} + +/*! + Returns \e true if this object has a in read or write lock; + otherwise returns \e false. + + \sa lockMode() +*/ +bool QtLockedFile::isLocked() const +{ + return m_lock_mode != NoLock; +} + +/*! + Returns the type of lock currently held by this object, or \e QtLockedFile::NoLock. + + \sa isLocked() +*/ +QtLockedFile::LockMode QtLockedFile::lockMode() const +{ + return m_lock_mode; +} + +/*! + \fn bool QtLockedFile::lock(LockMode mode, bool block = true) + + Obtains a lock of type \a mode. + + If \a block is true, this + function will block until the lock is acquired. If \a block is + false, this function returns \e false immediately if the lock cannot + be acquired. + + If this object already has a lock of type \a mode, this function returns \e true immediately. If this object has a lock of a different type than \a mode, the lock + is first released and then a new lock is obtained. + + This function returns \e true if, after it executes, the file is locked by this object, + and \e false otherwise. + + \sa unlock(), isLocked(), lockMode() +*/ + +/*! + \fn bool QtLockedFile::unlock() + + Releases a lock. + + If the object has no lock, this function returns immediately. + + This function returns \e true if, after it executes, the file is not locked by + this object, and \e false otherwise. + + \sa lock(), isLocked(), lockMode() +*/ + +/*! + \fn QtLockedFile::~QtLockedFile() + + Destroys the \e QtLockedFile object. If any locks were held, they are released. +*/ + +} // namespace SharedTools diff --git a/src/shared/qtlockedfile/qtlockedfile.h b/src/shared/qtlockedfile/qtlockedfile.h new file mode 100644 index 0000000000..d4aa9a59c0 --- /dev/null +++ b/src/shared/qtlockedfile/qtlockedfile.h @@ -0,0 +1,48 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#pragma once + +#include + +#if defined(Q_OS_WIN) +# if !defined(QT_QTLOCKEDFILE_EXPORT) && !defined(QT_QTLOCKEDFILE_IMPORT) +# define QT_QTLOCKEDFILE_EXPORT +# elif defined(QT_QTLOCKEDFILE_IMPORT) +# if defined(QT_QTLOCKEDFILE_EXPORT) +# undef QT_QTLOCKEDFILE_EXPORT +# endif +# define QT_QTLOCKEDFILE_EXPORT __declspec(dllimport) +# elif defined(QT_QTLOCKEDFILE_EXPORT) +# undef QT_QTLOCKEDFILE_EXPORT +# define QT_QTLOCKEDFILE_EXPORT __declspec(dllexport) +# endif +#else +# define QT_QTLOCKEDFILE_EXPORT +#endif + +namespace SharedTools { + +class QT_QTLOCKEDFILE_EXPORT QtLockedFile : public QFile +{ +public: + enum LockMode { NoLock = 0, ReadLock, WriteLock }; + + QtLockedFile(); + QtLockedFile(const QString &name); + ~QtLockedFile(); + + bool lock(LockMode mode, bool block = true); + bool unlock(); + bool isLocked() const; + LockMode lockMode() const; + +private: +#ifdef Q_OS_WIN + Qt::HANDLE m_semaphore_hnd; + Qt::HANDLE m_mutex_hnd; +#endif + LockMode m_lock_mode; +}; + +} // namespace SharedTools diff --git a/src/shared/qtlockedfile/qtlockedfile_unix.cpp b/src/shared/qtlockedfile/qtlockedfile_unix.cpp new file mode 100644 index 0000000000..e189f31472 --- /dev/null +++ b/src/shared/qtlockedfile/qtlockedfile_unix.cpp @@ -0,0 +1,82 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#include "qtlockedfile.h" + +#include +#include +#include +#include + +namespace SharedTools { + +bool QtLockedFile::lock(LockMode mode, bool block) +{ + if (!isOpen()) { + qWarning("QtLockedFile::lock(): file is not opened"); + return false; + } + + if (mode == NoLock) + return unlock(); + + if (mode == m_lock_mode) + return true; + + if (m_lock_mode != NoLock) + unlock(); + + struct flock fl; + fl.l_whence = SEEK_SET; + fl.l_start = 0; + fl.l_len = 0; + fl.l_type = (mode == ReadLock) ? F_RDLCK : F_WRLCK; + int cmd = block ? F_SETLKW : F_SETLK; + int ret = fcntl(handle(), cmd, &fl); + + if (ret == -1) { + if (errno != EINTR && errno != EAGAIN) + qWarning("QtLockedFile::lock(): fcntl: %s", strerror(errno)); + return false; + } + + + m_lock_mode = mode; + return true; +} + + +bool QtLockedFile::unlock() +{ + if (!isOpen()) { + qWarning("QtLockedFile::unlock(): file is not opened"); + return false; + } + + if (!isLocked()) + return true; + + struct flock fl; + fl.l_whence = SEEK_SET; + fl.l_start = 0; + fl.l_len = 0; + fl.l_type = F_UNLCK; + int ret = fcntl(handle(), F_SETLKW, &fl); + + if (ret == -1) { + qWarning("QtLockedFile::lock(): fcntl: %s", strerror(errno)); + return false; + } + + m_lock_mode = NoLock; + remove(); + return true; +} + +QtLockedFile::~QtLockedFile() +{ + if (isOpen()) + unlock(); +} + +} // namespace SharedTools diff --git a/src/shared/qtlockedfile/qtlockedfile_win.cpp b/src/shared/qtlockedfile/qtlockedfile_win.cpp new file mode 100644 index 0000000000..2f35635b55 --- /dev/null +++ b/src/shared/qtlockedfile/qtlockedfile_win.cpp @@ -0,0 +1,170 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#include "qtlockedfile.h" + +#include +#include + +namespace SharedTools { + +#define SEMAPHORE_PREFIX "QtLockedFile semaphore " +#define MUTEX_PREFIX "QtLockedFile mutex " +#define SEMAPHORE_MAX 100 + +static QString errorCodeToString(DWORD errorCode) +{ + QString result; + char *data = 0; + FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, + 0, errorCode, 0, + (char*)&data, 0, 0); + result = QString::fromLocal8Bit(data); + if (data != 0) + LocalFree(data); + + if (result.endsWith(QLatin1Char('\n'))) + result.truncate(result.length() - 1); + + return result; +} + +bool QtLockedFile::lock(LockMode mode, bool block) +{ + if (!isOpen()) { + qWarning("QtLockedFile::lock(): file is not opened"); + return false; + } + + if (mode == m_lock_mode) + return true; + + if (m_lock_mode != 0) + unlock(); + + if (m_semaphore_hnd == 0) { + QFileInfo fi(*this); + QString sem_name = QString::fromLatin1(SEMAPHORE_PREFIX) + + fi.absoluteFilePath().toLower(); + + m_semaphore_hnd = CreateSemaphoreW(0, SEMAPHORE_MAX, SEMAPHORE_MAX, + (TCHAR*)sem_name.utf16()); + + if (m_semaphore_hnd == 0) { + qWarning("QtLockedFile::lock(): CreateSemaphore: %s", + errorCodeToString(GetLastError()).toLatin1().constData()); + return false; + } + } + + bool gotMutex = false; + int decrement; + if (mode == ReadLock) { + decrement = 1; + } else { + decrement = SEMAPHORE_MAX; + if (m_mutex_hnd == 0) { + QFileInfo fi(*this); + QString mut_name = QString::fromLatin1(MUTEX_PREFIX) + + fi.absoluteFilePath().toLower(); + + m_mutex_hnd = CreateMutexW(NULL, FALSE, (TCHAR*)mut_name.utf16()); + + if (m_mutex_hnd == 0) { + qWarning("QtLockedFile::lock(): CreateMutex: %s", + errorCodeToString(GetLastError()).toLatin1().constData()); + return false; + } + } + DWORD res = WaitForSingleObject(m_mutex_hnd, block ? INFINITE : 0); + if (res == WAIT_TIMEOUT) + return false; + if (res == WAIT_FAILED) { + qWarning("QtLockedFile::lock(): WaitForSingleObject (mutex): %s", + errorCodeToString(GetLastError()).toLatin1().constData()); + return false; + } + gotMutex = true; + } + + for (int i = 0; i < decrement; ++i) { + DWORD res = WaitForSingleObject(m_semaphore_hnd, block ? INFINITE : 0); + if (res == WAIT_TIMEOUT) { + if (i) { + // A failed nonblocking rw locking. Undo changes to semaphore. + if (ReleaseSemaphore(m_semaphore_hnd, i, NULL) == 0) { + qWarning("QtLockedFile::unlock(): ReleaseSemaphore: %s", + errorCodeToString(GetLastError()).toLatin1().constData()); + // Fall through + } + } + if (gotMutex) + ReleaseMutex(m_mutex_hnd); + return false; + } + if (res != WAIT_OBJECT_0) { + if (gotMutex) + ReleaseMutex(m_mutex_hnd); + qWarning("QtLockedFile::lock(): WaitForSingleObject (semaphore): %s", + errorCodeToString(GetLastError()).toLatin1().constData()); + return false; + } + } + + m_lock_mode = mode; + if (gotMutex) + ReleaseMutex(m_mutex_hnd); + return true; +} + +bool QtLockedFile::unlock() +{ + if (!isOpen()) { + qWarning("QtLockedFile::unlock(): file is not opened"); + return false; + } + + if (!isLocked()) + return true; + + int increment; + if (m_lock_mode == ReadLock) + increment = 1; + else + increment = SEMAPHORE_MAX; + + DWORD ret = ReleaseSemaphore(m_semaphore_hnd, increment, 0); + if (ret == 0) { + qWarning("QtLockedFile::unlock(): ReleaseSemaphore: %s", + errorCodeToString(GetLastError()).toLatin1().constData()); + return false; + } + + m_lock_mode = QtLockedFile::NoLock; + remove(); + return true; +} + +QtLockedFile::~QtLockedFile() +{ + if (isOpen()) + unlock(); + if (m_mutex_hnd != 0) { + DWORD ret = CloseHandle(m_mutex_hnd); + if (ret == 0) { + qWarning("QtLockedFile::~QtLockedFile(): CloseHandle (mutex): %s", + errorCodeToString(GetLastError()).toLatin1().constData()); + } + m_mutex_hnd = 0; + } + if (m_semaphore_hnd != 0) { + DWORD ret = CloseHandle(m_semaphore_hnd); + if (ret == 0) { + qWarning("QtLockedFile::~QtLockedFile(): CloseHandle (semaphore): %s", + errorCodeToString(GetLastError()).toLatin1().constData()); + } + m_semaphore_hnd = 0; + } +} + +} // namespace SharedTools diff --git a/src/shared/qtsingleapplication/CMakeLists.txt b/src/shared/qtsingleapplication/CMakeLists.txt index 5b8e9c0271..fae6a08545 100644 --- a/src/shared/qtsingleapplication/CMakeLists.txt +++ b/src/shared/qtsingleapplication/CMakeLists.txt @@ -2,7 +2,7 @@ add_library(shared_qtsingleapplication STATIC qtsingleapplication.cpp qtsingleapplication.h qtlocalpeer.cpp qtlocalpeer.h ) -target_link_libraries(shared_qtsingleapplication Qt::Core Qt::Network Qt::Widgets) +target_link_libraries(shared_qtsingleapplication shared_qtlockedfile Qt::Core Qt::Network Qt::Widgets) target_include_directories(shared_qtsingleapplication PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}") if (WIN32) target_compile_definitions(shared_qtsingleapplication PRIVATE "QT_QTSINGLEAPPLICATION_EXPORT=__declspec(dllexport)") diff --git a/src/shared/qtsingleapplication/qtlocalpeer.cpp b/src/shared/qtsingleapplication/qtlocalpeer.cpp index 47dd3805ba..af72ece772 100644 --- a/src/shared/qtsingleapplication/qtlocalpeer.cpp +++ b/src/shared/qtsingleapplication/qtlocalpeer.cpp @@ -59,15 +59,16 @@ QtLocalPeer::QtLocalPeer(QObject *parent, const QString &appId) QString lockName = QDir(QDir::tempPath()).absolutePath() + QLatin1Char('/') + socketName + QLatin1String("-lockfile"); - lockFile.reset(new QLockFile(lockName)); + lockFile.setFileName(lockName); + lockFile.open(QIODevice::ReadWrite); } bool QtLocalPeer::isClient() { - if (lockFile->isLocked()) + if (lockFile.isLocked()) return false; - if (!lockFile->tryLock()) + if (!lockFile.lock(QtLockedFile::WriteLock, false)) return true; if (!QLocalServer::removeServer(socketName)) diff --git a/src/shared/qtsingleapplication/qtlocalpeer.h b/src/shared/qtsingleapplication/qtlocalpeer.h index 27578a7aca..67a0d42e2c 100644 --- a/src/shared/qtsingleapplication/qtlocalpeer.h +++ b/src/shared/qtsingleapplication/qtlocalpeer.h @@ -3,12 +3,11 @@ #pragma once +#include -#include #include #include -#include -#include +#include namespace SharedTools { @@ -32,8 +31,8 @@ protected: QString id; QString socketName; - QLocalServer* server{nullptr}; - QScopedPointer lockFile; + QLocalServer* server; + QtLockedFile lockFile; }; } // namespace SharedTools diff --git a/src/shared/qtsingleapplication/qtsingleapplication.cpp b/src/shared/qtsingleapplication/qtsingleapplication.cpp index b791d1875f..0f8fa8b6d1 100644 --- a/src/shared/qtsingleapplication/qtsingleapplication.cpp +++ b/src/shared/qtsingleapplication/qtsingleapplication.cpp @@ -4,9 +4,10 @@ #include "qtsingleapplication.h" #include "qtlocalpeer.h" +#include + #include #include -#include #include #include @@ -49,10 +50,11 @@ QtSingleApplication::QtSingleApplication(const QString &appId, int &argc, char * } } - // QLockFile is used to workaround QTBUG-10364 - QLockFile lockfile(instancesLockFilename(appSessionId)); + // QtLockedFile is used to workaround QTBUG-10364 + QtLockedFile lockfile(instancesLockFilename(appSessionId)); - lockfile.lock(); + lockfile.open(QtLockedFile::ReadWrite); + lockfile.lock(QtLockedFile::WriteLock); qint64 *pids = static_cast(instances->data()); if (!created) { // Find the first instance that it still running @@ -77,8 +79,9 @@ QtSingleApplication::~QtSingleApplication() if (!instances) return; const qint64 appPid = QCoreApplication::applicationPid(); - QLockFile lockfile(instancesLockFilename(QtLocalPeer::appSessionId(appId))); - lockfile.lock(); + QtLockedFile lockfile(instancesLockFilename(QtLocalPeer::appSessionId(appId))); + lockfile.open(QtLockedFile::ReadWrite); + lockfile.lock(QtLockedFile::WriteLock); // Rewrite array, removing current pid and previously crashed ones qint64 *pids = static_cast(instances->data()); qint64 *newpids = pids; -- cgit v1.2.3