Correct latent single instance lock file preventing launch

* Fixes #893
This commit is contained in:
Jonathan White 2017-09-13 22:54:30 -04:00 committed by Jonathan White
parent 4b6dbcaec4
commit 9ebe0b61eb
2 changed files with 44 additions and 28 deletions

View file

@ -81,8 +81,8 @@ Application::Application(int& argc, char** argv)
#ifdef Q_OS_UNIX #ifdef Q_OS_UNIX
, m_unixSignalNotifier(nullptr) , m_unixSignalNotifier(nullptr)
#endif #endif
, alreadyRunning(false) , m_alreadyRunning(false)
, lock(nullptr) , m_lockFile(nullptr)
{ {
#if defined(Q_OS_UNIX) && !defined(Q_OS_OSX) #if defined(Q_OS_UNIX) && !defined(Q_OS_OSX)
installNativeEventFilter(new XcbEventFilter()); installNativeEventFilter(new XcbEventFilter());
@ -99,40 +99,56 @@ Application::Application(int& argc, char** argv)
} }
QString identifier = "keepassxc"; QString identifier = "keepassxc";
if (!userName.isEmpty()) { if (!userName.isEmpty()) {
identifier.append("-"); identifier += "-" + userName;
identifier.append(userName); }
#ifdef QT_DEBUG #ifdef QT_DEBUG
// In DEBUG mode don't interfere with Release instances // In DEBUG mode don't interfere with Release instances
identifier.append("-DEBUG"); identifier += "-DEBUG";
#endif #endif
}
QString socketName = identifier + ".socket"; QString socketName = identifier + ".socket";
QString lockName = identifier + ".lock"; QString lockName = identifier + ".lock";
// According to documentation we should use RuntimeLocation on *nixes, but even Qt doesn't respect // According to documentation we should use RuntimeLocation on *nixes, but even Qt doesn't respect
// this and creates sockets in TempLocation, so let's be consistent. // this and creates sockets in TempLocation, so let's be consistent.
lock = new QLockFile(QStandardPaths::writableLocation(QStandardPaths::TempLocation) + "/" + lockName); m_lockFile = new QLockFile(QStandardPaths::writableLocation(QStandardPaths::TempLocation) + "/" + lockName);
lock->setStaleLockTime(0); m_lockFile->setStaleLockTime(0);
lock->tryLock(); m_lockFile->tryLock();
switch (lock->error()) {
switch (m_lockFile->error()) {
case QLockFile::NoError: case QLockFile::NoError:
server.setSocketOptions(QLocalServer::UserAccessOption); // No existing lock was found, start listener
server.listen(socketName); m_lockServer.setSocketOptions(QLocalServer::UserAccessOption);
connect(&server, SIGNAL(newConnection()), this, SIGNAL(anotherInstanceStarted())); m_lockServer.listen(socketName);
connect(&m_lockServer, SIGNAL(newConnection()), this, SIGNAL(anotherInstanceStarted()));
break; break;
case QLockFile::LockFailedError: { case QLockFile::LockFailedError: {
alreadyRunning = true;
// notify the other instance
// try several times, in case the other instance is still starting up
if (config()->get("SingleInstance").toBool()) { if (config()->get("SingleInstance").toBool()) {
// Attempt to connect to the existing instance
QLocalSocket client; QLocalSocket client;
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
client.connectToServer(socketName); client.connectToServer(socketName);
if (client.waitForConnected(150)) { if (client.waitForConnected(150)) {
// Connection succeeded, this will raise the existing window if minimized
client.abort(); client.abort();
m_alreadyRunning = true;
break; break;
} }
} }
if (!m_alreadyRunning) {
// If we get here then the original instance is likely dead
qWarning() << QCoreApplication::translate("Main",
"Existing single-instance lock file is invalid. Launching new instance.")
.toUtf8().constData();
// forceably reset the lock file
m_lockFile->removeStaleLockFile();
m_lockFile->tryLock();
// start the listen server
m_lockServer.setSocketOptions(QLocalServer::UserAccessOption);
m_lockServer.listen(socketName);
connect(&m_lockServer, SIGNAL(newConnection()), this, SIGNAL(anotherInstanceStarted()));
}
} }
break; break;
} }
@ -145,10 +161,10 @@ Application::Application(int& argc, char** argv)
Application::~Application() Application::~Application()
{ {
server.close(); m_lockServer.close();
if (lock) { if (m_lockFile) {
lock->unlock(); m_lockFile->unlock();
delete lock; delete m_lockFile;
} }
} }
@ -243,6 +259,6 @@ bool Application::isAlreadyRunning() const
// In DEBUG mode we can run unlimited instances // In DEBUG mode we can run unlimited instances
return false; return false;
#endif #endif
return config()->get("SingleInstance").toBool() && alreadyRunning; return config()->get("SingleInstance").toBool() && m_alreadyRunning;
} }

View file

@ -60,9 +60,9 @@ private:
static void handleUnixSignal(int sig); static void handleUnixSignal(int sig);
static int unixSignalSocket[2]; static int unixSignalSocket[2];
#endif #endif
bool alreadyRunning; bool m_alreadyRunning;
QLockFile* lock; QLockFile* m_lockFile;
QLocalServer server; QLocalServer m_lockServer;
}; };
#endif // KEEPASSX_APPLICATION_H #endif // KEEPASSX_APPLICATION_H