fix(apk): allow Steam cold launch after transient container removal

This commit is contained in:
toorux committed 2026-10-07 01:36:59 +08:00
1 parent 17af2ebfd5
commit dfce767894
2 files changed
+48 -4

No files matched your search

+26 -2
View File
@@ -3466,7 +3466,8 @@ setup_podman_mounts
r#"#!/bin/sh
printf '%s\n' "$*" >> '{commands}'
case "$1" in
inspect) case "$3" in *SteamBridge*) echo "fixture|{state}|$(cat '{state}')|{pid}";; *StartedAt*) echo "fixture|{state}|$(cat '{state}')";; *State.Pid*) echo "$(cat '{state}')|{pid}";; *) cat '{state}';; esac;;
inspect) case "$(cat '{state}')" in missing) echo 'Error: no such object: lepton-test' >&2; exit 125;; query-error) echo 'Error: storage permission denied' >&2; exit 125;; esac; case "$3" in *SteamBridge*) echo "fixture|{state}|$(cat '{state}')|{pid}";; *StartedAt*) echo "fixture|{state}|$(cat '{state}')";; *State.Pid*) echo "$(cat '{state}')|{pid}";; *) cat '{state}';; esac;;
container) case "$(cat '{state}')" in missing) exit 1;; query-error) exit 125;; *) exit 0;; esac;;
ps) if [ "$(cat '{state}')" = true ]; then case "$3" in *Pid*) echo 'lepton-test|{pid}';; *) echo lepton-test;; esac; fi;;
stop) echo false > '{state}'; echo stopped;;
cp) /bin/cp -f "$2" '{incoming}';;
@@ -3821,6 +3822,25 @@ setup_props
assert!(!f.home.join(".local/share/applications").exists());
}
#[test]
fn steam_container_probe_distinguishes_removed_stopped_and_query_failures() {
let f = Fixture::new();
let db = load(&f.home).unwrap();
let (_, c) = app(&f.home, &db, "test/com.example.app").unwrap();
fs::write(f.dir.path().join("commands"), "").unwrap();
assert!(steam_bridge::current_instance(&c).unwrap().is_some());
for state in ["false", "missing"] {
fs::write(f.dir.path().join("running"), state).unwrap();
assert!(steam_bridge::current_instance(&c).unwrap().is_none());
}
fs::write(f.dir.path().join("running"), "query-error").unwrap();
assert!(steam_bridge::current_instance(&c).is_err());
assert_eq!(fs::read_to_string(f.save_file()).unwrap(), "saved progress");
let commands = fs::read_to_string(f.dir.path().join("commands")).unwrap();
assert!(!commands
.lines()
.any(|line| line.starts_with("exec ") || line.starts_with("stop ")));
}
#[test]
fn steam_wrapper_launch_and_stop_preserve_data_and_reject_unowned_requests() {
let f = Fixture::new();
let id = "test/com.example.app";
@@ -3840,7 +3860,11 @@ setup_props
assert!(steam_bridge::test_request(&f.home, id, "wrong", "start").is_err());
// A direct-running container must never be restarted to obtain Steam ownership.
assert!(steam_bridge::test_request(&f.home, id, "test-token", "start").is_err());
fs::write(f.dir.path().join("running"), "false").unwrap();
fs::write(f.dir.path().join("running"), "query-error").unwrap();
assert!(steam_bridge::test_request(&f.home, id, "test-token", "start").is_err());
// Lepton --rm leaves no Podman object after shutdown. Cold Steam launch
// must work without requiring a previously created/stopped object.
fs::write(f.dir.path().join("running"), "missing").unwrap();
assert_eq!(
steam_bridge::test_request(&f.home, id, "test-token", "start").unwrap()["started"],
true
+22 -2
View File
@@ -103,7 +103,7 @@ fn record(home: &Path, id: &str, token: &str) -> Result<Record> {
);
Ok(r.clone())
}
fn current_instance(c: &Container) -> Result<Option<String>> {
pub(super) fn current_instance(c: &Container) -> Result<Option<String>> {
let mut cmd = crate::process::tool("podman");
cmd.args([
"inspect",
@@ -111,7 +111,27 @@ fn current_instance(c: &Container) -> Result<Option<String>> {
"{{/*SteamBridge*/}}{{.Id}}|{{.State.StartedAt}}|{{.State.Running}}|{{.State.Pid}}",
&format!("lepton-{}", c.name),
]);
let text = output(cmd, Duration::from_secs(3), None)?;
let text = match output(cmd, Duration::from_secs(3), None) {
Ok(text) => text,
Err(error) => {
// Lepton removes its transient Podman object when stopped. Only
// Podman's explicit "absent" exit code is safe to treat as stopped;
// permission/storage/runtime errors must not authorize a new boot.
let exists = crate::process::command_output_timeout(
crate::process::tool("podman").args([
"container",
"exists",
&format!("lepton-{}", c.name),
]),
Duration::from_secs(3),
false,
)?;
if exists.status.code() == Some(1) {
return Ok(None);
}
return Err(error.context("Cannot verify Steam APK container state"));
}
};
let fields: Vec<_> = text.trim().split('|').collect();
ensure!(
fields.len() == 4