Each app writes $HOME/.cache/crafter-debug/instances/<id>.json (0600, in a 0700 directory) and holds an flock on <id>.lock while it lives. Every `flatpak run` is its own pid namespace, so pids collide and can neither name an instance nor tell whether it lives; a random id names it and the lock says it lives, since flock works across sandboxes on the shared filesystem. An app killed without its destructor leaves its files with the lock free, and the next listing removes them. The lock is created under a temporary name, locked, then renamed, as in Crafter.Review's LifetimeLock, so it is never seen unlocked while its app lives. Inside a Flatpak the record also carries the sandbox's instance id (for `flatpak enter`) and the host pid of its init (to end the whole sandbox from the host). project.cpp now generates :BuildInfo per core variant: a hash of the library's sources and the path of the client built with it. App and client share the core, so they report the same id exactly when built from the same sources; this is the safety net under building the client in the same pass as the app. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
72 lines
2.9 KiB
C++
72 lines
2.9 KiB
C++
// SPDX-License-Identifier: LGPL-3.0-only
|
|
// SPDX-FileCopyrightText: Copyright (C) 2026 Catcrafts®
|
|
|
|
// How crafter-debug finds running apps. Each app writes
|
|
// $HOME/.cache/crafter-debug/instances/<instanceId>.json, readable by its
|
|
// user only, and holds an flock on <instanceId>.lock for as long as it runs.
|
|
//
|
|
// Spelled with $HOME, not $XDG_CACHE_HOME: inside the CrafterBuild Flatpak
|
|
// XDG_CACHE_HOME points into ~/.var/app/..., which a native crafter-build
|
|
// would not see, while $HOME/.cache is the same path for both. Every
|
|
// `flatpak run` is its own sandbox with its own pid namespace, so pids
|
|
// collide and cannot name an instance or tell whether it lives: a random
|
|
// instance id names it, and the lock says whether it lives, since flock works
|
|
// across sandboxes on the shared filesystem. An app killed without running
|
|
// its destructor leaves its files behind with the lock free, and the next
|
|
// listing removes them. The pattern is Crafter.Review's LifetimeLock.
|
|
export module Crafter.Debug.Core:Discovery;
|
|
import std;
|
|
|
|
export namespace Crafter::Debug {
|
|
struct InstanceRecord {
|
|
std::string name;
|
|
std::string instanceId;
|
|
// The app's own pid, in its own pid namespace: what a debugger
|
|
// started inside that sandbox attaches to.
|
|
std::int64_t pid = 0;
|
|
// Inside a Flatpak: the sandbox's [Instance] instance-id (for
|
|
// `flatpak enter`), and the host pid of its init (bwrapinfo.json's
|
|
// child-pid), which `kill -KILL` ends the whole sandbox through.
|
|
std::string flatpakInstance;
|
|
std::int64_t hostInitPid = 0;
|
|
std::string exe;
|
|
std::uint16_t port = 0;
|
|
std::string token;
|
|
std::uint32_t protocol = 0;
|
|
std::string sourceId;
|
|
// The crafter-debug client built with this app.
|
|
std::string client;
|
|
// Seconds since the epoch.
|
|
std::int64_t startedAt = 0;
|
|
};
|
|
|
|
// $CRAFTER_DEBUG_DIR when set (tests), else $HOME/.cache/crafter-debug/instances.
|
|
std::filesystem::path DiscoveryDirectory();
|
|
|
|
// An app's presence: writes the record and holds the lock while it lives.
|
|
class Registration {
|
|
public:
|
|
// Fills in instanceId, pid, the Flatpak fields, exe and startedAt.
|
|
// Throws std::system_error when the directory or files cannot be made.
|
|
explicit Registration(InstanceRecord record);
|
|
~Registration();
|
|
Registration(const Registration&) = delete;
|
|
Registration& operator=(const Registration&) = delete;
|
|
|
|
const InstanceRecord& Record() const { return record; }
|
|
|
|
private:
|
|
InstanceRecord record;
|
|
std::filesystem::path recordPath;
|
|
std::filesystem::path lockPath;
|
|
std::int32_t lockFd = -1;
|
|
};
|
|
|
|
struct Instance {
|
|
InstanceRecord record;
|
|
std::filesystem::path recordPath;
|
|
};
|
|
|
|
// Every live instance, newest first; the files of dead ones are removed.
|
|
std::vector<Instance> ListInstances();
|
|
}
|