fix(updater): run the handoff script via systemd-run so it survives the app's scope
On uwsm/Hyprland the app runs in a systemd scope cgroup; a detached child is swept away when the app quits, which killed the swap mid-flight on every in-app update attempt. systemd-run gives the installer its own transient unit that outlives the scope; detached spawn stays as the non-systemd fallback.
This commit is contained in:
parent
c064e3aab1
commit
12977e1a77
2 changed files with 35 additions and 7 deletions
4
package-lock.json
generated
4
package-lock.json
generated
|
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"name": "folio",
|
||||
"version": "0.1.7",
|
||||
"version": "0.1.8",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "folio",
|
||||
"version": "0.1.7",
|
||||
"version": "0.1.8",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@tiptap/core": "^2.27.2",
|
||||
|
|
|
|||
|
|
@ -1286,12 +1286,40 @@ handleIpc("folio:performUpdate", async () => {
|
|||
}),
|
||||
{ mode: 0o700 }
|
||||
);
|
||||
// IMPORTANT: on systemd desktops (Hyprland/uwsm) the app runs inside a
|
||||
// systemd scope cgroup, and a plain detached child stays in that cgroup —
|
||||
// when the app quits, systemd sweeps the scope and kills the swap script
|
||||
// mid-run (root cause of the "update failed" reports: the handoff died
|
||||
// before swapping, and the app was relaunched from the old tree).
|
||||
// systemd-run puts the script in its own transient unit that outlives us;
|
||||
// verified to survive on this machine. Fall back to a detached spawn for
|
||||
// non-systemd sessions.
|
||||
const { spawn } = await import("child_process");
|
||||
const child = spawn("/bin/sh", [script], { detached: true, stdio: "ignore" });
|
||||
child.on("error", (err) => {
|
||||
console.error("[folio] updater spawn failed:", err.message);
|
||||
});
|
||||
child.unref();
|
||||
let handedOff = false;
|
||||
try {
|
||||
const { execFileSync } = await import("child_process");
|
||||
execFileSync("systemd-run", [
|
||||
"--user", "--quiet", "--collect",
|
||||
`--description=Folio updater handoff`,
|
||||
"/bin/sh", script,
|
||||
], { timeout: 10_000, stdio: "ignore" });
|
||||
handedOff = true;
|
||||
} catch {
|
||||
try {
|
||||
const child = spawn("/bin/sh", [script], { detached: true, stdio: "ignore" });
|
||||
child.on("error", (err) => {
|
||||
console.error("[folio] updater spawn failed:", err.message);
|
||||
});
|
||||
child.unref();
|
||||
handedOff = true;
|
||||
} catch (e) {
|
||||
void e;
|
||||
}
|
||||
}
|
||||
if (!handedOff) {
|
||||
try { fs.appendFileSync(updateLog, new Date().toISOString() + " FAIL: could not start swap script\n"); } catch { /* ignore */ }
|
||||
return { error: "Could not start the installer. Your current version is unchanged." };
|
||||
}
|
||||
// Quit so the swap script can replace the app directory.
|
||||
setTimeout(() => app.quit(), 300);
|
||||
return { ok: true, version: rel.version };
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue