mirror of
https://github.com/phantomptr/ps5upload.git
synced 2026-10-22 03:42:55 -05:00
Upload, install, convert and manage PS5 game packages over the network. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
87 lines
3.6 KiB
C
87 lines
3.6 KiB
C
#ifndef PS5UPLOAD2_INSTANCE_VERDICT_H
|
|
#define PS5UPLOAD2_INSTANCE_VERDICT_H
|
|
|
|
#include <stdint.h>
|
|
|
|
/*
|
|
* How did the PREVIOUS payload instance end?
|
|
*
|
|
* The ownership record (runtime_write_ownership / runtime_clear_ownership)
|
|
* is already an exit marker: written at startup, unlinked on a graceful
|
|
* exit. What was missing was reading it as a verdict.
|
|
*
|
|
* This matters because SIGKILL cannot be caught. An instance killed by
|
|
* another payload's "replace my predecessor" sweep, or by the OOM killer,
|
|
* leaves no log line of its own — the ONLY evidence is an ownership record
|
|
* it never got to unlink, plus a pid that is no longer alive.
|
|
*/
|
|
typedef enum {
|
|
PS5UPLOAD2_PRIOR_CLEAN = 0,
|
|
PS5UPLOAD2_PRIOR_KILLED_EXTERNALLY = 1,
|
|
PS5UPLOAD2_PRIOR_WEDGED = 2,
|
|
PS5UPLOAD2_PRIOR_STALE = 3,
|
|
/* Alive when this instance started, then handed over cooperatively. The
|
|
* normal relaunch-over-a-running-helper case. */
|
|
PS5UPLOAD2_PRIOR_REPLACED = 4,
|
|
} ps5upload2_prior_verdict_t;
|
|
|
|
/*
|
|
* `record_present` — an ownership record existed at startup.
|
|
* `prior_started_at` — its started_at_unix field, 0 when absent/unreadable.
|
|
* `boottime` — kern.boottime in the same clock domain, 0 when the
|
|
* sysctl is unavailable.
|
|
* `prior_pid_alive` — kill(pid, 0) succeeded for its recorded pid.
|
|
*
|
|
* Fails safe: any unknowable input yields STALE rather than a confident
|
|
* claim. The ownership file lives on persistent /data and survives reboots,
|
|
* so a record that predates this boot says nothing about this session.
|
|
*/
|
|
static inline ps5upload2_prior_verdict_t
|
|
instance_verdict_classify(int record_present,
|
|
uint64_t prior_started_at,
|
|
uint64_t boottime,
|
|
int prior_pid_alive) {
|
|
if (!record_present) return PS5UPLOAD2_PRIOR_CLEAN;
|
|
if (boottime == 0 || prior_started_at == 0 || prior_started_at < boottime) {
|
|
return PS5UPLOAD2_PRIOR_STALE;
|
|
}
|
|
if (prior_pid_alive) return PS5UPLOAD2_PRIOR_WEDGED;
|
|
return PS5UPLOAD2_PRIOR_KILLED_EXTERNALLY;
|
|
}
|
|
|
|
/*
|
|
* Refine the startup verdict once the takeover's outcome is known.
|
|
*
|
|
* The classifier has to run BEFORE the takeover (afterwards the ownership
|
|
* record belongs to this instance), and at that point a perfectly healthy
|
|
* predecessor is alive — so every ordinary relaunch over a running helper was
|
|
* reported as "wedged". Measured: five relaunches in a row on a FW 5.10
|
|
* console, every one "wedged", every predecessor handing over cleanly. That
|
|
* label then sent a crash investigation after a stuck process that did not
|
|
* exist. "Wedged" now means what it says: alive, and it would NOT hand over.
|
|
*/
|
|
static inline ps5upload2_prior_verdict_t
|
|
instance_verdict_after_takeover(ps5upload2_prior_verdict_t at_startup,
|
|
int cooperative_takeover_ok) {
|
|
if (at_startup == PS5UPLOAD2_PRIOR_WEDGED && cooperative_takeover_ok) {
|
|
return PS5UPLOAD2_PRIOR_REPLACED;
|
|
}
|
|
return at_startup;
|
|
}
|
|
|
|
/* Wire name. snake_case: this value crosses the STATUS_ACK JSON boundary
|
|
* into serde on the engine side. */
|
|
static inline const char *
|
|
instance_verdict_name(ps5upload2_prior_verdict_t v) {
|
|
switch (v) {
|
|
case PS5UPLOAD2_PRIOR_CLEAN: return "clean";
|
|
case PS5UPLOAD2_PRIOR_KILLED_EXTERNALLY: return "killed_externally";
|
|
case PS5UPLOAD2_PRIOR_WEDGED: return "wedged";
|
|
case PS5UPLOAD2_PRIOR_STALE: return "stale";
|
|
case PS5UPLOAD2_PRIOR_REPLACED: return "replaced";
|
|
}
|
|
return "unknown";
|
|
}
|
|
|
|
#endif /* PS5UPLOAD2_INSTANCE_VERDICT_H */
|