Argus.Analyses.DeferredStartupDeadlock (Panoptes v0.13.0)

Copy Markdown View Source

Deferred startup deadlock detection.

handle_continue/2 runs after init/1 returns, so a sync call from inside handle_continue does NOT block the parent supervisor — that's why this is a separate analysis from sync_call_in_init. But three specific patterns make handle_continue sync calls genuinely problematic:

  1. Mutual continue cycleA.handle_continue sync-calls B, B.handle_continue sync-calls A. Both processes return from init, the supervisor proceeds, but neither child ever processes its mailbox.
  2. Continue calls later sibling — under :one_for_one, calling a sibling that starts at a later position in the supervisor's child list races against that sibling's startup.
  3. Continue calls parent supervisor — calling Supervisor.which_children/1 on the parent while it's still mid-start_link. The supervisor isn't reading its mailbox yet.

Plus a defensive variant: when the continue body is wrapped in try/catch :exit, _, the literal deadlock is suppressed but the worker enters a supervisor restart loop.

Output relations

  • mutual_continue_deadlock(mod_a, mod_b) — both modules' continues sync-call each other.
  • continue_to_later_sibling(sup, caller, callee, caller_pos, callee_pos) — caller's continue sync-calls a sibling started later in the same supervisor.
  • continue_to_parent_supervisor(worker, sup) — worker's continue sync-calls back into its parent supervisor.
  • continue_crash_loop_risk(sup, worker) — defensive try/catch around the call converts the deadlock into a supervisor restart loop.
  • init_timeout_deferral(mod, site, timeout_ms) — init/1 returns {:ok, state, timeout}; the work behind :timeout is cancelled by any message that arrives first.

Finding severities

  • mutual_continue_deadlock:error. Both processes block before ever reading their mailboxes; neither can answer the other, by construction.
  • init_timeout_deferral:info. Whether the deferred work is load-bearing is the reader's call; the shape is fragile either way.
  • continue_to_later_sibling, continue_to_parent_supervisor, continue_crash_loop_risk:warning. Startup races and restart loops whose outcome depends on timing rather than being guaranteed on every boot.