From a5c531f0a421394e8950b94f6c6a359f3720a41a Mon Sep 17 00:00:00 2001 From: Chocobo1 Date: Sat, 30 Oct 2021 17:33:58 +0800 Subject: [PATCH 1/2] Create lock file in config folder instead of temp folder Some linux distros seem to alter TMPDIR environment variable and therefore hamper qbt ability to find the lock files. So use config folder instead of TMPDIR folder to create/locate the lock files. Note that this change will also make qbt become one instance per-user instead of one instance per-system. Closes #15646. --- src/app/application.cpp | 10 +---- src/app/applicationinstancemanager.cpp | 16 +++---- src/app/applicationinstancemanager.h | 5 +-- src/app/qtlocalpeer/qtlocalpeer.cpp | 59 ++++++-------------------- src/app/qtlocalpeer/qtlocalpeer.h | 8 ++-- src/app/qtlocalpeer/qtlockedfile.h | 1 + 6 files changed, 29 insertions(+), 70 deletions(-) diff --git a/src/app/application.cpp b/src/app/application.cpp index e02205995..b5783feb0 100644 --- a/src/app/application.cpp +++ b/src/app/application.cpp @@ -154,17 +154,11 @@ Application::Application(int &argc, char **argv) const QString profileDir = portableModeEnabled ? QDir(QCoreApplication::applicationDirPath()).absoluteFilePath(DEFAULT_PORTABLE_MODE_PROFILE_DIR) : m_commandLineArgs.profileDir; -#ifdef Q_OS_WIN - const QString instanceId = (profileDir + (m_commandLineArgs.configurationName.isEmpty() ? QString {} : ('/' + m_commandLineArgs.configurationName))).toLower(); -#else - const QString instanceId = profileDir + (m_commandLineArgs.configurationName.isEmpty() ? QString {} : ('/' + m_commandLineArgs.configurationName)); -#endif - const QString appId = QLatin1String("qBittorrent-") + Utils::Misc::getUserIDString() + '@' + instanceId; - m_instanceManager = new ApplicationInstanceManager {appId, this}; - Profile::initInstance(profileDir, m_commandLineArgs.configurationName, (m_commandLineArgs.relativeFastresumePaths || portableModeEnabled)); + m_instanceManager = new ApplicationInstanceManager {Profile::instance()->location(SpecialFolder::Config), this}; + Logger::initInstance(); SettingsStorage::initInstance(); Preferences::initInstance(); diff --git a/src/app/applicationinstancemanager.cpp b/src/app/applicationinstancemanager.cpp index 0feed1586..6a15f0471 100644 --- a/src/app/applicationinstancemanager.cpp +++ b/src/app/applicationinstancemanager.cpp @@ -28,24 +28,27 @@ #include "applicationinstancemanager.h" +#include + #ifdef Q_OS_WIN #include -#endif #include #include +#endif #include "qtlocalpeer/qtlocalpeer.h" -ApplicationInstanceManager::ApplicationInstanceManager(const QString &appId, QObject *parent) +ApplicationInstanceManager::ApplicationInstanceManager(const QString &instancePath, QObject *parent) : QObject {parent} - , m_peer {new QtLocalPeer {this, appId}} + , m_peer {new QtLocalPeer {instancePath, this}} , m_isFirstInstance {!m_peer->isClient()} { connect(m_peer, &QtLocalPeer::messageReceived, this, &ApplicationInstanceManager::messageReceived); #ifdef Q_OS_WIN - auto sharedMem = new QSharedMemory {appId + QLatin1String {"-shared-memory-key"}, this}; + const QString sharedMemoryKey = instancePath + QLatin1String {"/shared-memory"}; + auto sharedMem = new QSharedMemory {sharedMemoryKey, this}; if (m_isFirstInstance) { // First instance creates shared memory and store PID @@ -79,8 +82,3 @@ bool ApplicationInstanceManager::sendMessage(const QString &message, const int t { return m_peer->sendMessage(message, timeout); } - -QString ApplicationInstanceManager::appId() const -{ - return m_peer->applicationId(); -} diff --git a/src/app/applicationinstancemanager.h b/src/app/applicationinstancemanager.h index b186958ff..91ad7c2fd 100644 --- a/src/app/applicationinstancemanager.h +++ b/src/app/applicationinstancemanager.h @@ -32,16 +32,15 @@ class QtLocalPeer; -class ApplicationInstanceManager : public QObject +class ApplicationInstanceManager final : public QObject { Q_OBJECT Q_DISABLE_COPY_MOVE(ApplicationInstanceManager) public: - explicit ApplicationInstanceManager(const QString &appId, QObject *parent = nullptr); + explicit ApplicationInstanceManager(const QString &instancePath, QObject *parent = nullptr); bool isFirstInstance() const; - QString appId() const; public slots: bool sendMessage(const QString &message, int timeout = 5000); diff --git a/src/app/qtlocalpeer/qtlocalpeer.cpp b/src/app/qtlocalpeer/qtlocalpeer.cpp index b4b329abf..70673d150 100644 --- a/src/app/qtlocalpeer/qtlocalpeer.cpp +++ b/src/app/qtlocalpeer/qtlocalpeer.cpp @@ -68,20 +68,16 @@ #include "qtlocalpeer.h" -#if defined(Q_OS_UNIX) -#include -#include -#include +#include + +#if defined(Q_OS_WIN) +#include #endif -#include #include -#include +#include #include #include -#include - -#include "base/utils/misc.h" namespace QtLP_Private { @@ -96,41 +92,14 @@ namespace QtLP_Private const char* QtLocalPeer::ack = "ack"; -QtLocalPeer::QtLocalPeer(QObject *parent, const QString &appId) +QtLocalPeer::QtLocalPeer(const QString &path, QObject *parent) : QObject(parent) - , id(appId) + , socketName(path + QLatin1String("/ipc-socket")) + , server(new QLocalServer(this)) { - QString prefix = id; - if (id.isEmpty()) - { - id = QCoreApplication::applicationFilePath(); -#if defined(Q_OS_WIN) - id = id.toLower(); -#endif - prefix = id.section(QLatin1Char('/'), -1); - } - prefix.remove(QRegularExpression("[^a-zA-Z]")); - prefix.truncate(6); - - QByteArray idc = id.toUtf8(); - quint16 idNum = qChecksum(idc.constData(), idc.size()); - socketName = QLatin1String("qtsingleapp-") + prefix - + QLatin1Char('-') + QString::number(idNum, 16); - -#if defined(Q_OS_WIN) - DWORD sessionId = 0; - ::ProcessIdToSessionId(GetCurrentProcessId(), &sessionId); - socketName += (QLatin1Char('-') + QString::number(sessionId, 16)); -#else - socketName += (QLatin1Char('-') + QString::number(::getuid(), 16)); -#endif - - server = new QLocalServer(this); server->setSocketOptions(QLocalServer::UserAccessOption); - QString lockName = QDir(QDir::tempPath()).absolutePath() - + QLatin1Char('/') + socketName - + QLatin1String("-lockfile"); - lockFile.setFileName(lockName); + + lockFile.setFileName(path + QLatin1String("/lockfile")); lockFile.open(QIODevice::ReadWrite); } @@ -156,12 +125,13 @@ bool QtLocalPeer::isClient() // ### Workaround if (!res && server->serverError() == QAbstractSocket::AddressInUseError) { - QFile::remove(QDir::cleanPath(QDir::tempPath())+QLatin1Char('/')+socketName); + QFile::remove(socketName); res = server->listen(socketName); } #endif if (!res) qWarning("QtSingleCoreApplication: listen on local socket failed, %s", qPrintable(server->errorString())); + connect(server, &QLocalServer::newConnection, this, &QtLocalPeer::receiveConnection); return false; } @@ -204,11 +174,6 @@ bool QtLocalPeer::sendMessage(const QString &message, const int timeout) return res; } -QString QtLocalPeer::applicationId() const -{ - return id; -} - void QtLocalPeer::receiveConnection() { QLocalSocket* socket = server->nextPendingConnection(); diff --git a/src/app/qtlocalpeer/qtlocalpeer.h b/src/app/qtlocalpeer/qtlocalpeer.h index 51954cfc2..9e4ceee90 100644 --- a/src/app/qtlocalpeer/qtlocalpeer.h +++ b/src/app/qtlocalpeer/qtlocalpeer.h @@ -68,21 +68,23 @@ #pragma once +#include + #include "qtlockedfile.h" class QLocalServer; -class QtLocalPeer : public QObject +class QtLocalPeer final : public QObject { Q_OBJECT + Q_DISABLE_COPY_MOVE(QtLocalPeer) public: - QtLocalPeer(QObject *parent = nullptr, const QString &appId = QString()); + QtLocalPeer(const QString &path, QObject *parent = nullptr); ~QtLocalPeer() override; bool isClient(); bool sendMessage(const QString &message, int timeout); - QString applicationId() const; signals: void messageReceived(const QString &message); diff --git a/src/app/qtlocalpeer/qtlockedfile.h b/src/app/qtlocalpeer/qtlockedfile.h index f17eeb04f..53852d225 100644 --- a/src/app/qtlocalpeer/qtlockedfile.h +++ b/src/app/qtlocalpeer/qtlockedfile.h @@ -71,6 +71,7 @@ #include #ifdef Q_OS_WIN +#include #include #endif From 180deb867a071ebd7635003ce2fc3868cbca90d6 Mon Sep 17 00:00:00 2001 From: Chocobo1 Date: Thu, 28 Oct 2021 14:15:23 +0800 Subject: [PATCH 2/2] Use char array directly This eliminates the possibility of reassigning the pointer to another address. --- src/base/profile_p.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/base/profile_p.cpp b/src/base/profile_p.cpp index c382f5d8b..a7c3ec5ae 100644 --- a/src/base/profile_p.cpp +++ b/src/base/profile_p.cpp @@ -169,9 +169,9 @@ SettingsPtr Private::CustomProfile::applicationSettings(const QString &name) con { // here we force QSettings::IniFormat format always because we need it to be portable across platforms #if defined(Q_OS_WIN) || defined(Q_OS_MACOS) - constexpr const char *CONF_FILE_EXTENSION = ".ini"; + const char CONF_FILE_EXTENSION[] = ".ini"; #else - constexpr const char *CONF_FILE_EXTENSION = ".conf"; + const char CONF_FILE_EXTENSION[] = ".conf"; #endif const QString settingsFileName {QDir(configLocation()).absoluteFilePath(name + QLatin1String(CONF_FILE_EXTENSION))}; return SettingsPtr(new QSettings(settingsFileName, QSettings::IniFormat));