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.
This commit is contained in:
Ilya Fedin 2021-11-25 05:32:31 +04:00 committed by John Preston
parent d89aab08bf
commit 7ff7473db6
3 changed files with 37 additions and 15 deletions

View file

@ -460,7 +460,6 @@ void Launcher::processArguments() {
auto parseMap = std::map<QByteArray, KeyFormat> { auto parseMap = std::map<QByteArray, KeyFormat> {
{ "-debug" , KeyFormat::NoValues }, { "-debug" , KeyFormat::NoValues },
{ "-freetype" , KeyFormat::NoValues }, { "-freetype" , KeyFormat::NoValues },
{ "-many" , KeyFormat::NoValues },
{ "-key" , KeyFormat::OneValue }, { "-key" , KeyFormat::OneValue },
{ "-autostart" , KeyFormat::NoValues }, { "-autostart" , KeyFormat::NoValues },
{ "-fixprevious" , KeyFormat::NoValues }, { "-fixprevious" , KeyFormat::NoValues },
@ -499,7 +498,6 @@ void Launcher::processArguments() {
gUseFreeType = parseResult.contains("-freetype"); gUseFreeType = parseResult.contains("-freetype");
gDebugMode = parseResult.contains("-debug"); gDebugMode = parseResult.contains("-debug");
gManyInstance = parseResult.contains("-many");
gKeyFile = parseResult.value("-key", {}).join(QString()).toLower(); gKeyFile = parseResult.value("-key", {}).join(QString()).toLower();
gKeyFile = gKeyFile.replace(QRegularExpression("[^a-z0-9\\-_]"), {}); gKeyFile = gKeyFile.replace(QRegularExpression("[^a-z0-9\\-_]"), {});
gLaunchMode = parseResult.contains("-autostart") ? LaunchModeAutoStart gLaunchMode = parseResult.contains("-autostart") ? LaunchModeAutoStart

View file

@ -29,6 +29,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/effects/animations.h" #include "ui/effects/animations.h"
#include "app.h" #include "app.h"
#include <QtCore/QLockFile>
#include <QtGui/QSessionManager> #include <QtGui/QSessionManager>
#include <QtGui/QScreen> #include <QtGui/QScreen>
#include <qpa/qplatformscreen.h> #include <qpa/qplatformscreen.h>
@ -99,10 +100,35 @@ int Sandbox::start() {
if (!Core::UpdaterDisabled()) { if (!Core::UpdaterDisabled()) {
_updateChecker = std::make_unique<Core::UpdateChecker>(); _updateChecker = std::make_unique<Core::UpdateChecker>();
} }
const auto d = QFile::encodeName(QDir(cWorkingDir()).absolutePath());
char h[33] = { 0 }; {
hashMd5Hex(d.constData(), d.size(), h); const auto d = QFile::encodeName(QDir(cWorkingDir()).absolutePath());
_localServerName = Platform::SingleInstanceLocalServerName(h); 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<QLockFile>(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( connect(
&_localSocket, &_localSocket,
@ -149,13 +175,8 @@ int Sandbox::start() {
restartHint, restartHint,
Qt::DirectConnection); Qt::DirectConnection);
if (cManyInstance()) { LOG(("Connecting local socket to %1...").arg(_localServerName));
LOG(("Many instance allowed, starting...")); _localSocket.connectToServer(_localServerName);
singleInstanceChecked();
} else {
LOG(("Connecting local socket to %1...").arg(_localServerName));
_localSocket.connectToServer(_localServerName);
}
if (QuitOnStartRequested) { if (QuitOnStartRequested) {
closeApplication(); closeApplication();
@ -339,12 +360,12 @@ void Sandbox::socketError(QLocalSocket::LocalSocketError e) {
void Sandbox::singleInstanceChecked() { void Sandbox::singleInstanceChecked() {
if (cManyInstance()) { if (cManyInstance()) {
Logs::multipleInstances(); LOG(("App Info: Detected another instance"));
} }
Ui::DisableCustomScaling(); Ui::DisableCustomScaling();
refreshGlobalProxy(); refreshGlobalProxy();
if (!Logs::started() || (!cManyInstance() && !Logs::instanceChecked())) { if (!Logs::started() || !Logs::instanceChecked()) {
new NotStartedWindow(); new NotStartedWindow();
return; return;
} }

View file

@ -15,6 +15,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include <QtNetwork/QLocalSocket> #include <QtNetwork/QLocalSocket>
#include <QtCore/QAbstractNativeEventFilter> #include <QtCore/QAbstractNativeEventFilter>
class QLockFile;
namespace Core { namespace Core {
class Launcher; class Launcher;
@ -119,6 +121,7 @@ private:
QLocalServer _localServer; QLocalServer _localServer;
QLocalSocket _localSocket; QLocalSocket _localSocket;
LocalClients _localClients; LocalClients _localClients;
std::unique_ptr<QLockFile> _lockFile;
bool _secondInstance = false; bool _secondInstance = false;
bool _started = false; bool _started = false;
static bool QuitOnStartRequested; static bool QuitOnStartRequested;