From 7ff7473db6ac640114f743b01a5cdba679a4d0e8 Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Thu, 25 Nov 2021 05:32:31 +0400 Subject: [PATCH] Auto-check for many instance This option was invented when single instance check wasn't adapted for -workdir. Now, -workdir can work without -many and this option is redudant, but auto-update prevention is helpful. Let's autodetect whether the binary is already running with a lock file. --- Telegram/SourceFiles/core/launcher.cpp | 2 -- Telegram/SourceFiles/core/sandbox.cpp | 47 +++++++++++++++++++------- Telegram/SourceFiles/core/sandbox.h | 3 ++ 3 files changed, 37 insertions(+), 15 deletions(-) diff --git a/Telegram/SourceFiles/core/launcher.cpp b/Telegram/SourceFiles/core/launcher.cpp index eda856e5b..b9b927c44 100644 --- a/Telegram/SourceFiles/core/launcher.cpp +++ b/Telegram/SourceFiles/core/launcher.cpp @@ -460,7 +460,6 @@ void Launcher::processArguments() { auto parseMap = std::map { { "-debug" , KeyFormat::NoValues }, { "-freetype" , KeyFormat::NoValues }, - { "-many" , KeyFormat::NoValues }, { "-key" , KeyFormat::OneValue }, { "-autostart" , KeyFormat::NoValues }, { "-fixprevious" , KeyFormat::NoValues }, @@ -499,7 +498,6 @@ void Launcher::processArguments() { gUseFreeType = parseResult.contains("-freetype"); gDebugMode = parseResult.contains("-debug"); - gManyInstance = parseResult.contains("-many"); gKeyFile = parseResult.value("-key", {}).join(QString()).toLower(); gKeyFile = gKeyFile.replace(QRegularExpression("[^a-z0-9\\-_]"), {}); gLaunchMode = parseResult.contains("-autostart") ? LaunchModeAutoStart diff --git a/Telegram/SourceFiles/core/sandbox.cpp b/Telegram/SourceFiles/core/sandbox.cpp index a113e88aa..b8d481454 100644 --- a/Telegram/SourceFiles/core/sandbox.cpp +++ b/Telegram/SourceFiles/core/sandbox.cpp @@ -29,6 +29,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/effects/animations.h" #include "app.h" +#include #include #include #include @@ -99,10 +100,35 @@ int Sandbox::start() { if (!Core::UpdaterDisabled()) { _updateChecker = std::make_unique(); } - const auto d = QFile::encodeName(QDir(cWorkingDir()).absolutePath()); - char h[33] = { 0 }; - hashMd5Hex(d.constData(), d.size(), h); - _localServerName = Platform::SingleInstanceLocalServerName(h); + + { + const auto d = QFile::encodeName(QDir(cWorkingDir()).absolutePath()); + char h[33] = { 0 }; + hashMd5Hex(d.constData(), d.size(), h); + _localServerName = Platform::SingleInstanceLocalServerName(h); + } + + { + const auto d = QFile::encodeName(cExeDir() + cExeName()); + QByteArray h; + h.resize(32); + hashMd5Hex(d.constData(), d.size(), h.data()); + _lockFile = std::make_unique(QDir::tempPath() + '/' + h + '-' + cGUIDStr()); + _lockFile->setStaleLockTime(0); + if (!_lockFile->tryLock() && _launcher->customWorkingDir()) { + // On Windows, QLockFile has problems detecting a stale lock + // if the machine's hostname contains characters outside the US-ASCII character set. + if constexpr (Platform::IsWindows()) { + // QLockFile::removeStaleLockFile returns false on Windows, + // when the application owning the lock is still running. + if (!_lockFile->removeStaleLockFile()) { + gManyInstance = true; + } + } else { + gManyInstance = true; + } + } + } connect( &_localSocket, @@ -149,13 +175,8 @@ int Sandbox::start() { restartHint, Qt::DirectConnection); - if (cManyInstance()) { - LOG(("Many instance allowed, starting...")); - singleInstanceChecked(); - } else { - LOG(("Connecting local socket to %1...").arg(_localServerName)); - _localSocket.connectToServer(_localServerName); - } + LOG(("Connecting local socket to %1...").arg(_localServerName)); + _localSocket.connectToServer(_localServerName); if (QuitOnStartRequested) { closeApplication(); @@ -339,12 +360,12 @@ void Sandbox::socketError(QLocalSocket::LocalSocketError e) { void Sandbox::singleInstanceChecked() { if (cManyInstance()) { - Logs::multipleInstances(); + LOG(("App Info: Detected another instance")); } Ui::DisableCustomScaling(); refreshGlobalProxy(); - if (!Logs::started() || (!cManyInstance() && !Logs::instanceChecked())) { + if (!Logs::started() || !Logs::instanceChecked()) { new NotStartedWindow(); return; } diff --git a/Telegram/SourceFiles/core/sandbox.h b/Telegram/SourceFiles/core/sandbox.h index 7362f5554..944dee65e 100644 --- a/Telegram/SourceFiles/core/sandbox.h +++ b/Telegram/SourceFiles/core/sandbox.h @@ -15,6 +15,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include #include +class QLockFile; + namespace Core { class Launcher; @@ -119,6 +121,7 @@ private: QLocalServer _localServer; QLocalSocket _localSocket; LocalClients _localClients; + std::unique_ptr _lockFile; bool _secondInstance = false; bool _started = false; static bool QuitOnStartRequested;