{"version":"2.1.248","anchor":"the-background-daemon-defers-restarts-and-idle-exits-while-a","canonical_anchor":"the-background-daemon-defers-restarts-and-idle-exits-while-a","heading":"The background daemon defers restarts and idle exits while an upgrade is pending","tier":"notice","area":"Background Daemon","scope":null,"heads_up":null,"url":"https:\/\/changelogs.core-directive.com\/v\/2.1.248\/e\/the-background-daemon-defers-restarts-and-idle-exits-while-a","release_url":"https:\/\/changelogs.core-directive.com\/v\/2.1.248","markdown":"### The background daemon defers restarts and idle exits while an upgrade is pending\n\nThe background service waits for your turn to finish before restarting for an upgrade.\n\n**What**\n\nThe long-running background service that supervises Claude Code worker sessions now handles binary upgrades without cutting anyone off. When a newer binary appears, it holds off restarting while any worker is mid-turn, re-checking on each poll for up to 30 minutes before restarting anyway, and its idle timer reschedules itself rather than shutting the service down while an upgrade is in flight. Shutdown paths now record why the service stopped, and the control socket reports upgrade state to callers.\n\n**Details**\n\n- Deferral of the restart is on when the server sends no config: the `tengu_daemon_upgrade_defer_busy` flag has a compiled fallback of true.\n- Workers report their busy state to the supervisor over the inter-process channel as `{ type: \"rc_busy\", busy: g }`, and the supervisor tracks when each last reported plus a running count of busy workers.\n- The wait cap is an option defaulting to 1800000 ms (30 minutes) and appears in the log as `capped at ${Math.round(T \/ 60000)}m`.\n- Deferral is abandoned early if the new binary reverts to the old one, the daemon is already shutting down, or the poll itself errors.\n- A `tengu_daemon_upgrade_deferred_busy` event records the busy worker count, how long the restart was deferred, whether the cap expired, and the phase it was in.\n- Shutdown reports a cause of either \"upgrade\" or \"yield\", with \"upgrade\" only reported when the daemon was not also displaced by another instance taking over.\n- The previously scattered shutdown checks collapse into one predicate driving the shutting-down state.\n- The control-socket nudge returns a restarting flag and an upgrade-pending flag instead of the single boolean it returned before.\n\n**Evidence**\n\n`binary at ${W} changed but ${be} registry worker(s) report a mid-turn session`, `tengu_daemon_upgrade_deferred_busy`, `onNudge: async () => ({`\n\n- Flag `tengu_daemon_upgrade_defer_busy`: Not enough to say (read for one account on one subscription tier against v2.1.248; this account: no value returned, anonymous baseline: no value returned, compiled default: on)\n- Area: Background Daemon\n- Tier: You'll notice\n- Useful: 3\/5\n- Signal: 3\/5"}