Fix single instance behavior if multiple users use syncthingtray in parallel

Create a distinct server for each user so they don't interfere with each
other. Otherwise the instance of the second user tries to connect to the
instance started by the first user which fails and therefore breaks the
single instance behavior for the second user.
This commit is contained in:
Martchus 2022-06-17 21:46:06 +02:00
parent 05e98e22dd
commit dea8e5ae68
1 changed files with 55 additions and 2 deletions

View File

@ -11,12 +11,59 @@
#include <iostream>
#include <memory>
#ifdef Q_OS_WINDOWS
#include <windows.h>
// needs to be included after windows.h
#include <sddl.h>
#else
#include <unistd.h>
#endif
using namespace std;
using namespace CppUtilities;
using namespace CppUtilities::EscapeCodes;
namespace QtGui {
#ifdef Q_OS_WINDOWS
static QString getCurrentProcessSIDAsString()
{
auto res = QString();
auto processToken = HANDLE();
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &processToken)) {
std::cerr << Phrases::Error << "Unable to determine current user: OpenProcessToken failed with " << GetLastError() << Phrases::EndFlush;
return res;
}
auto bufferSize = DWORD();
if (!GetTokenInformation(processToken, TokenUser, nullptr, 0, &bufferSize) && (GetLastError() != ERROR_INSUFFICIENT_BUFFER)) {
std::cerr << Phrases::Error << "Unable to determine current user: GetTokenInformation failed with " << GetLastError() << Phrases::EndFlush;
CloseHandle(processToken);
return res;
}
auto buffer = std::vector<BYTE>();
buffer.resize(bufferSize);
auto userToken = reinterpret_cast<PTOKEN_USER>(buffer.data());
if (!GetTokenInformation(processToken, TokenUser, userToken, bufferSize, &bufferSize)) {
std::cerr << Phrases::Error << "Unable to determine current user: GetTokenInformation failed with " << GetLastError() << Phrases::EndFlush;
CloseHandle(processToken);
return res;
}
auto stringSid = LPWSTR();
if (!ConvertSidToStringSidW(userToken->User.Sid, &stringSid)) {
std::cerr << Phrases::Error << "Unable to determine current user: ConvertSidToStringSid failed with " << GetLastError() << Phrases::EndFlush;
CloseHandle(processToken);
return res;
}
res = QString::fromWCharArray(stringSid);
LocalFree(stringSid);
CloseHandle(processToken);
return res;
}
#endif
SingleInstance::SingleInstance(int argc, const char *const *argv, bool newInstance, QObject *parent)
: QObject(parent)
, m_server(nullptr)
@ -26,7 +73,13 @@ SingleInstance::SingleInstance(int argc, const char *const *argv, bool newInstan
}
// check for running instance
const QString appId(QCoreApplication::applicationName() % QStringLiteral(" by ") % QCoreApplication::organizationName());
static const auto appId = QString(QCoreApplication::applicationName() % QChar('-') % QCoreApplication::organizationName() % QChar('-') %
#ifdef Q_OS_WINDOWS
getCurrentProcessSIDAsString()
#else
QString::number(getuid())
#endif
);
passArgsToRunningInstance(argc, argv, appId);
// no previous instance running
@ -36,7 +89,7 @@ SingleInstance::SingleInstance(int argc, const char *const *argv, bool newInstan
m_server = new QLocalServer(this);
connect(m_server, &QLocalServer::newConnection, this, &SingleInstance::handleNewConnection);
if (!m_server->listen(appId)) {
cerr << Phrases::Error << "Unable to launch as single instance application" << Phrases::EndFlush;
cerr << Phrases::Error << "Unable to launch as single instance application as " << appId.toStdString() << Phrases::EndFlush;
}
}