Skip to content

Commit 0e6518a

Browse files
committed
core/command: improve dead instance selection
Prints dead instances if they exist, as well as allowing dead instance selection for a substring if no live instances exist.
1 parent 86591f1 commit 0e6518a

File tree

8 files changed

+86
-24
lines changed

8 files changed

+86
-24
lines changed

src/core/instanceinfo.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@
33
#include <qdatastream.h>
44

55
QDataStream& operator<<(QDataStream& stream, const InstanceInfo& info) {
6-
stream << info.instanceId << info.configPath << info.shellId << info.launchTime;
6+
stream << info.instanceId << info.configPath << info.shellId << info.launchTime << info.pid;
77
return stream;
88
}
99

1010
QDataStream& operator>>(QDataStream& stream, InstanceInfo& info) {
11-
stream >> info.instanceId >> info.configPath >> info.shellId >> info.launchTime;
11+
stream >> info.instanceId >> info.configPath >> info.shellId >> info.launchTime >> info.pid;
1212
return stream;
1313
}
1414

src/core/instanceinfo.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,14 @@
33
#include <qdatetime.h>
44
#include <qlogging.h>
55
#include <qstring.h>
6+
#include <sys/types.h>
67

78
struct InstanceInfo {
89
QString instanceId;
910
QString configPath;
1011
QString shellId;
1112
QDateTime launchTime;
13+
pid_t pid = -1;
1214

1315
static InstanceInfo CURRENT; // NOLINT
1416
};

src/core/paths.cpp

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <qdir.h>
1010
#include <qlogging.h>
1111
#include <qloggingcategory.h>
12+
#include <qpair.h>
1213
#include <qstandardpaths.h>
1314
#include <qtenvironmentvariables.h>
1415
#include <qtversionchecks.h>
@@ -367,29 +368,30 @@ bool QsPaths::checkLock(const QString& path, InstanceLockInfo* info, bool allowD
367368
return true;
368369
}
369370

370-
QVector<InstanceLockInfo> QsPaths::collectInstances(const QString& path, bool fallbackDead) {
371+
QPair<QVector<InstanceLockInfo>, QVector<InstanceLockInfo>>
372+
QsPaths::collectInstances(const QString& path) {
371373
qCDebug(logPaths) << "Collecting instances from" << path;
372-
auto instances = QVector<InstanceLockInfo>();
374+
auto liveInstances = QVector<InstanceLockInfo>();
375+
auto deadInstances = QVector<InstanceLockInfo>();
373376
auto dir = QDir(path);
374377

375378
InstanceLockInfo info;
376379
for (auto& entry: dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot)) {
377380
auto path = dir.filePath(entry);
378381

379-
if (QsPaths::checkLock(path, &info, fallbackDead)) {
380-
if (fallbackDead && info.pid != -1) {
381-
fallbackDead = false;
382-
instances.clear();
383-
}
384-
382+
if (QsPaths::checkLock(path, &info, true)) {
385383
qCDebug(logPaths).nospace() << "Found instance " << info.instance.instanceId << " (pid "
386384
<< info.pid << ") at " << path;
387385

388-
instances.push_back(info);
386+
if (info.pid == -1) {
387+
deadInstances.push_back(info);
388+
} else {
389+
liveInstances.push_back(info);
390+
}
389391
} else {
390392
qCDebug(logPaths) << "Skipped potential instance at" << path;
391393
}
392394
}
393395

394-
return instances;
396+
return qMakePair(liveInstances, deadInstances);
395397
}

src/core/paths.hpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#pragma once
22
#include <qdatetime.h>
33
#include <qdir.h>
4+
#include <qpair.h>
45
#include <qtypes.h>
56

67
#include "instanceinfo.hpp"
@@ -22,7 +23,8 @@ class QsPaths {
2223
static QString ipcPath(const QString& id);
2324
static bool
2425
checkLock(const QString& path, InstanceLockInfo* info = nullptr, bool allowDead = false);
25-
static QVector<InstanceLockInfo> collectInstances(const QString& path, bool fallbackDead = false);
26+
static QPair<QVector<InstanceLockInfo>, QVector<InstanceLockInfo>>
27+
collectInstances(const QString& path);
2628

2729
QDir* baseRunDir();
2830
QDir* shellRunDir();

src/launch/command.cpp

Lines changed: 62 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include <cerrno>
44
#include <cstdio>
55
#include <cstring>
6+
#include <utility>
67

78
#include <qconfig.h>
89
#include <qcontainerfwd.h>
@@ -177,14 +178,33 @@ int selectInstance(CommandState& cmd, InstanceLockInfo* instance, bool deadFallb
177178
}
178179
} else if (!cmd.instance.id->isEmpty()) {
179180
path = basePath->filePath("by-pid");
180-
auto instances = QsPaths::collectInstances(path, deadFallback);
181+
auto [liveInstances, deadInstances] = QsPaths::collectInstances(path);
181182

182-
instances.removeIf([&](const InstanceLockInfo& info) {
183+
liveInstances.removeIf([&](const InstanceLockInfo& info) {
183184
return !info.instance.instanceId.startsWith(*cmd.instance.id);
184185
});
185186

187+
deadInstances.removeIf([&](const InstanceLockInfo& info) {
188+
return !info.instance.instanceId.startsWith(*cmd.instance.id);
189+
});
190+
191+
auto instances = liveInstances.isEmpty() && deadFallback ? deadInstances : liveInstances;
192+
186193
if (instances.isEmpty()) {
187-
qCInfo(logBare) << "No running instances start with" << *cmd.instance.id;
194+
if (deadFallback) {
195+
qCInfo(logBare) << "No instances start with" << *cmd.instance.id;
196+
} else {
197+
qCInfo(logBare) << "No running instances start with" << *cmd.instance.id;
198+
199+
if (!deadInstances.isEmpty()) {
200+
qCInfo(logBare) << "Some dead instances match:";
201+
202+
for (auto& instance: deadInstances) {
203+
qCInfo(logBare).noquote() << " -" << instance.instance.instanceId;
204+
}
205+
}
206+
}
207+
188208
return -1;
189209
} else if (instances.length() != 1) {
190210
qCInfo(logBare) << "More than one instance starts with" << *cmd.instance.id;
@@ -208,14 +228,29 @@ int selectInstance(CommandState& cmd, InstanceLockInfo* instance, bool deadFallb
208228

209229
path = QDir(basePath->filePath("by-path")).filePath(pathId);
210230

211-
auto instances = QsPaths::collectInstances(path, deadFallback);
231+
auto [liveInstances, deadInstances] = QsPaths::collectInstances(path);
232+
233+
auto instances = liveInstances;
234+
if (instances.isEmpty() && deadFallback) {
235+
instances = deadInstances;
236+
}
237+
212238
sortInstances(
213239
instances,
214240
cmd.config.newest || (!instances.empty() && instances.first().pid == -1)
215241
);
216242

217243
if (instances.isEmpty()) {
218-
qCInfo(logBare) << "No running instances for" << configFilePath;
244+
if (liveInstances.isEmpty() && deadInstances.length() > 1) {
245+
qCInfo(logBare) << "No running instances for" << configFilePath;
246+
qCInfo(logBare) << "Dead instances:";
247+
sortInstances(deadInstances, cmd.config.newest);
248+
for (auto& instance: deadInstances) {
249+
qCInfo(logBare).noquote() << " -" << instance.instance.instanceId;
250+
}
251+
} else {
252+
qCInfo(logBare) << "No running instances for" << configFilePath;
253+
}
219254
return -1;
220255
}
221256

@@ -276,7 +311,18 @@ int listInstances(CommandState& cmd) {
276311
path = QDir(basePath->filePath("by-path")).filePath(pathId);
277312
}
278313

279-
auto instances = QsPaths::collectInstances(path);
314+
auto [liveInstances, deadInstances] = QsPaths::collectInstances(path);
315+
316+
sortInstances(liveInstances, cmd.config.newest);
317+
318+
QList<InstanceLockInfo> instances;
319+
if (cmd.instance.includeDead) {
320+
sortInstances(deadInstances, cmd.config.newest);
321+
instances = std::move(deadInstances);
322+
instances.append(liveInstances);
323+
} else {
324+
instances = std::move(liveInstances);
325+
}
280326

281327
if (instances.isEmpty()) {
282328
if (cmd.instance.all) {
@@ -286,7 +332,6 @@ int listInstances(CommandState& cmd) {
286332
qCInfo(logBare) << "Use --all to list all instances.";
287333
}
288334
} else {
289-
sortInstances(instances, cmd.config.newest);
290335

291336
if (cmd.output.json) {
292337
auto array = QJsonArray();
@@ -295,7 +340,7 @@ int listInstances(CommandState& cmd) {
295340
auto json = QJsonObject();
296341

297342
json["id"] = instance.instance.instanceId;
298-
json["pid"] = instance.pid;
343+
json["pid"] = instance.instance.pid;
299344
json["shell_id"] = instance.instance.shellId;
300345
json["config_path"] = instance.instance.configPath;
301346
json["launch_time"] = instance.instance.launchTime.toString(Qt::ISODate);
@@ -319,12 +364,18 @@ int listInstances(CommandState& cmd) {
319364
.arg(remMinutes)
320365
.arg(remSeconds);
321366

367+
auto isDead = instance.pid == -1;
368+
auto gray = !cmd.log.noColor && isDead;
369+
322370
qCInfo(logBare).noquote().nospace()
323-
<< "Instance " << instance.instance.instanceId << ":\n"
324-
<< " Process ID: " << instance.pid << '\n'
371+
<< (gray ? "\033[90m" : "") << "Instance " << instance.instance.instanceId
372+
<< (isDead ? " (dead)" : "") << ":\n"
373+
<< " Process ID: " << instance.instance.pid << '\n'
325374
<< " Shell ID: " << instance.instance.shellId << '\n'
326375
<< " Config path: " << instance.instance.configPath << '\n'
327-
<< " Launch time: " << launchTimeStr << " (running for " << runtimeStr << ")\n";
376+
<< " Launch time: " << launchTimeStr
377+
<< (isDead ? "" : " (running for " + runtimeStr + ")") << '\n'
378+
<< (gray ? "\033[0m" : "");
328379
}
329380
}
330381
}

src/launch/launch.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ int launch(const LaunchArgs& args, char** argv, QCoreApplication* coreApplicatio
128128
.configPath = args.configPath,
129129
.shellId = shellId,
130130
.launchTime = qs::Common::LAUNCH_TIME,
131+
.pid = getpid(),
131132
};
132133

133134
#if CRASH_REPORTER

src/launch/launch_p.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ struct CommandState {
6161
QStringOption id;
6262
pid_t pid = -1; // NOLINT (include)
6363
bool all = false;
64+
bool includeDead = false;
6465
} instance;
6566

6667
struct {

src/launch/parsecommand.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,9 @@ int parseCommand(int argc, char** argv, CommandState& state) {
163163

164164
sub->add_flag("-j,--json", state.output.json, "Output the list as a json.");
165165

166+
sub->add_flag("--show-dead", state.instance.includeDead)
167+
->description("Include dead instances in the list.");
168+
166169
addConfigSelection(sub, true)->excludes(all);
167170
addLoggingOptions(sub, false, true);
168171

0 commit comments

Comments
 (0)