core/command: allow qs log to retrieve logs of dead instances

If no live instances are found matching the current config, the
youngest dead instance will be used instead.
This commit is contained in:
outfoxxed 2025-03-19 05:15:50 -07:00
parent 0662c37d67
commit eabf79ebb6
Signed by: outfoxxed
GPG key ID: 4C88A185FB89301E
3 changed files with 28 additions and 16 deletions

View file

@ -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<InstanceLockInfo> QsPaths::collectInstances(const QString& path) {
QVector<InstanceLockInfo> QsPaths::collectInstances(const QString& path, bool fallbackDead) {
qCDebug(logPaths) << "Collecting instances from" << path;
auto instances = QVector<InstanceLockInfo>();
auto dir = QDir(path);
@ -296,13 +298,18 @@ QVector<InstanceLockInfo> 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;
}
}

View file

@ -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<InstanceLockInfo> collectInstances(const QString& path);
static bool
checkLock(const QString& path, InstanceLockInfo* info = nullptr, bool allowDead = false);
static QVector<InstanceLockInfo> collectInstances(const QString& path, bool fallbackDead = false);
QDir* cacheDir();
QDir* baseRunDir();

View file

@ -109,7 +109,7 @@ void sortInstances(QVector<InstanceLockInfo>& 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");