diff --git a/src/core/paths.cpp b/src/core/paths.cpp index e49a9d4..0129d88 100644 --- a/src/core/paths.cpp +++ b/src/core/paths.cpp @@ -262,7 +262,7 @@ void QsPaths::createLock() { } } -bool QsPaths::checkLock(const QString& path, InstanceLockInfo* info) { +bool QsPaths::checkLock(const QString& path, InstanceLockInfo* info, bool allowDead) { auto file = QFile(QDir(path).filePath("instance.lock")); if (!file.open(QFile::ReadOnly)) return false; @@ -275,10 +275,12 @@ bool QsPaths::checkLock(const QString& path, InstanceLockInfo* info) { }; fcntl(file.handle(), F_GETLK, &lock); // NOLINT - if (lock.l_type == F_UNLCK) return false; + auto isLocked = lock.l_type != F_UNLCK; + + if (!isLocked && !allowDead) return false; if (info) { - info->pid = lock.l_pid; + info->pid = isLocked ? lock.l_pid : -1; auto stream = QDataStream(&file); stream >> info->instance; @@ -287,7 +289,7 @@ bool QsPaths::checkLock(const QString& path, InstanceLockInfo* info) { return true; } -QVector QsPaths::collectInstances(const QString& path) { +QVector QsPaths::collectInstances(const QString& path, bool fallbackDead) { qCDebug(logPaths) << "Collecting instances from" << path; auto instances = QVector(); auto dir = QDir(path); @@ -296,13 +298,18 @@ QVector QsPaths::collectInstances(const QString& path) { for (auto& entry: dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot)) { auto path = dir.filePath(entry); - if (QsPaths::checkLock(path, &info)) { - qCDebug(logPaths).nospace() << "Found live instance " << info.instance.instanceId << " (pid " + if (QsPaths::checkLock(path, &info, fallbackDead)) { + if (fallbackDead && info.pid != -1) { + fallbackDead = false; + instances.clear(); + } + + qCDebug(logPaths).nospace() << "Found instance " << info.instance.instanceId << " (pid " << info.pid << ") at " << path; instances.push_back(info); } else { - qCDebug(logPaths) << "Skipped dead instance at" << path; + qCDebug(logPaths) << "Skipped potential instance at" << path; } } diff --git a/src/core/paths.hpp b/src/core/paths.hpp index b20d408..8d95fae 100644 --- a/src/core/paths.hpp +++ b/src/core/paths.hpp @@ -20,8 +20,9 @@ public: static QDir crashDir(const QString& id); static QString basePath(const QString& id); static QString ipcPath(const QString& id); - static bool checkLock(const QString& path, InstanceLockInfo* info = nullptr); - static QVector collectInstances(const QString& path); + static bool + checkLock(const QString& path, InstanceLockInfo* info = nullptr, bool allowDead = false); + static QVector collectInstances(const QString& path, bool fallbackDead = false); QDir* cacheDir(); QDir* baseRunDir(); diff --git a/src/launch/command.cpp b/src/launch/command.cpp index 00ad613..b8f1d15 100644 --- a/src/launch/command.cpp +++ b/src/launch/command.cpp @@ -109,7 +109,7 @@ void sortInstances(QVector& list, bool newestFirst) { }); }; -int selectInstance(CommandState& cmd, InstanceLockInfo* instance) { +int selectInstance(CommandState& cmd, InstanceLockInfo* instance, bool deadFallback = false) { auto* basePath = QsPaths::instance()->baseRunDir(); if (!basePath) return -1; @@ -117,13 +117,13 @@ int selectInstance(CommandState& cmd, InstanceLockInfo* instance) { if (cmd.instance.pid != -1) { path = QDir(basePath->filePath("by-pid")).filePath(QString::number(cmd.instance.pid)); - if (!QsPaths::checkLock(path, instance)) { + if (!QsPaths::checkLock(path, instance, deadFallback)) { qCInfo(logBare) << "No instance found for pid" << cmd.instance.pid; return -1; } } else if (!cmd.instance.id->isEmpty()) { path = basePath->filePath("by-pid"); - auto instances = QsPaths::collectInstances(path); + auto instances = QsPaths::collectInstances(path, deadFallback); instances.removeIf([&](const InstanceLockInfo& info) { return !info.instance.instanceId.startsWith(*cmd.instance.id); @@ -136,7 +136,8 @@ int selectInstance(CommandState& cmd, InstanceLockInfo* instance) { qCInfo(logBare) << "More than one instance starts with" << *cmd.instance.id; for (auto& instance: instances) { - qCInfo(logBare).noquote() << " -" << instance.instance.instanceId; + qCInfo(logBare).noquote() << " -" << instance.instance.instanceId + << (instance.pid == -1 ? " (dead)" : ""); } return -1; @@ -153,8 +154,11 @@ int selectInstance(CommandState& cmd, InstanceLockInfo* instance) { path = QDir(basePath->filePath("by-path")).filePath(pathId); - auto instances = QsPaths::collectInstances(path); - sortInstances(instances, cmd.config.newest); + auto instances = QsPaths::collectInstances(path, deadFallback); + sortInstances( + instances, + cmd.config.newest || (!instances.empty() && instances.first().pid == -1) + ); if (instances.isEmpty()) { qCInfo(logBare) << "No running instances for" << configFilePath; @@ -172,7 +176,7 @@ int readLogFile(CommandState& cmd) { if (path.isEmpty()) { InstanceLockInfo instance; - auto r = selectInstance(cmd, &instance); + auto r = selectInstance(cmd, &instance, true); if (r != 0) return r; path = QDir(QsPaths::basePath(instance.instance.instanceId)).filePath("log.qslog");