Skip to content

Commit 971f838

Browse files
committed
Refactor background daemon termination to use SIGTERM for graceful shutdown, with fallback to SIGKILL if necessary. Improve signal handling for clean exit on stop requests. Fixes #114
1 parent a5c919e commit 971f838

1 file changed

Lines changed: 46 additions & 8 deletions

File tree

‎src/core/background_update_service.vala‎

Lines changed: 46 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -139,15 +139,17 @@ X-XDP-Autostart=com.github.AppManager
139139
*/
140140
public static void kill_daemon() {
141141
try {
142-
// Use pkill with SIGKILL (-9) to ensure the daemon is terminated
142+
// Send SIGTERM (pkill's default) so the daemon runs its shutdown
143+
// handler and exits cleanly, letting the AppImage runtime unmount
144+
// its dwarfs mount. SIGKILL (-9) would orphan that mount in /tmp.
143145
// Match just "--background-update" to avoid issues with path variations
144146
// Use "--" to indicate end of options since pattern starts with "-"
145-
string[] argv = { "pkill", "-9", "-f", "--", "--background-update" };
147+
string[] argv = { "pkill", "-f", "--", "--background-update" };
146148
int exit_status;
147149
Process.spawn_sync(null, argv, null, GLib.SpawnFlags.SEARCH_PATH, null, null, null, out exit_status);
148-
debug("Killed background daemon (exit status: %d)", exit_status);
150+
debug("Stopped background daemon (exit status: %d)", exit_status);
149151
} catch (SpawnError e) {
150-
warning("Failed to kill background daemon: %s", e.message);
152+
warning("Failed to stop background daemon: %s", e.message);
151153
}
152154
}
153155

@@ -172,7 +174,17 @@ X-XDP-Autostart=com.github.AppManager
172174
Thread.usleep(100000); // 100ms
173175
}
174176

175-
warning("Background daemon did not terminate within 5 seconds");
177+
// Migration must not race a live daemon. If the graceful SIGTERM
178+
// didn't land in time (e.g. daemon blocked mid update-check), escalate
179+
// to SIGKILL. This can orphan the dwarfs mount, but a safe migration
180+
// outweighs a stale /tmp symlink that cleanup_stale() reaps next launch.
181+
warning("Background daemon did not terminate within 5 seconds; sending SIGKILL");
182+
try {
183+
string[] argv = { "pkill", "-9", "-f", "--", "--background-update" };
184+
Process.spawn_sync(null, argv, null, GLib.SpawnFlags.SEARCH_PATH, null, null, null, null);
185+
} catch (SpawnError e) {
186+
warning("Failed to force-kill background daemon: %s", e.message);
187+
}
176188
return true;
177189
}
178190

@@ -490,6 +502,24 @@ X-XDP-Autostart=com.github.AppManager
490502
public void run_daemon() {
491503
log_debug("background daemon: starting persistent service");
492504

505+
var loop = new MainLoop();
506+
507+
// Quit cleanly when the session manager / systemd asks us to stop.
508+
// GApplication installs no signal handlers and this daemon runs its
509+
// own MainLoop, so without this it would ignore SIGTERM on shutdown
510+
// and be SIGKILLed after the stop timeout (issue #114). Install the
511+
// handlers first so a stop request during the initial check is honored.
512+
Unix.signal_add(Posix.Signal.TERM, () => {
513+
log_debug("background daemon: SIGTERM received, stopping");
514+
loop.quit();
515+
return Source.REMOVE;
516+
});
517+
Unix.signal_add(Posix.Signal.INT, () => {
518+
log_debug("background daemon: SIGINT received, stopping");
519+
loop.quit();
520+
return Source.REMOVE;
521+
});
522+
493523
// On login, re-notify about staged updates (notify-only mode only)
494524
check_staged_updates_on_login();
495525

@@ -503,7 +533,7 @@ X-XDP-Autostart=com.github.AppManager
503533

504534
// Check periodically whether we should perform an update check
505535
// This allows the daemon to respect interval changes without restart
506-
Timeout.add_seconds(DAEMON_CHECK_INTERVAL, () => {
536+
var check_source_id = Timeout.add_seconds(DAEMON_CHECK_INTERVAL, () => {
507537
if (!settings.get_boolean("auto-check-updates")) {
508538
log_debug("background daemon: auto-check disabled, skipping");
509539
return Source.CONTINUE;
@@ -517,9 +547,17 @@ X-XDP-Autostart=com.github.AppManager
517547
return Source.CONTINUE;
518548
});
519549

520-
// Run the main loop - this blocks until the session ends
521-
var loop = new MainLoop();
550+
// Run the main loop - this blocks until a stop signal quits it
522551
loop.run();
552+
553+
// Clean shutdown: drop the periodic check and any D-Bus subscription
554+
// so we exit promptly instead of leaking sources and getting killed.
555+
Source.remove(check_source_id);
556+
if (dbus_connection != null && action_signal_id != 0) {
557+
dbus_connection.signal_unsubscribe(action_signal_id);
558+
action_signal_id = 0;
559+
}
560+
log_debug("background daemon: stopped");
523561
}
524562

525563
private void log_debug(string message) {

0 commit comments

Comments
 (0)