Skip to content

signal+main: exit with code 1 on programmatic shutdown#10944

Open
kpshukla wants to merge 2 commits into
lightningnetwork:masterfrom
kpshukla:fix/5625-exit-code-on-healthcheck-shutdown
Open

signal+main: exit with code 1 on programmatic shutdown#10944
kpshukla wants to merge 2 commits into
lightningnetwork:masterfrom
kpshukla:fix/5625-exit-code-on-healthcheck-shutdown

Conversation

@kpshukla

Copy link
Copy Markdown

Summary

Fixes #5625

When lnd shuts itself down due to a health check failure (e.g. the chain backend becomes unreachable after the configured number of retries), it previously exited with code 0. This caused systemd and other process managers to treat the exit as intentional — meaning Restart=on-failure would not trigger and the node would remain offline until manually restarted.

Changes:

  • signal/signal.go: Add a requestedShutdown uint32 field to Interceptor, set atomically in mainInterruptHandler when shutdown originates from shutdownRequestChannel (i.e. RequestShutdown()) rather than from an OS signal. Expose it via a new RequestedShutdown() bool method.
  • cmd/lnd/main.go: After lnd.Main() returns without error, check shutdownInterceptor.RequestedShutdown(). If set, call os.Exit(1) so process managers can distinguish an abnormal shutdown from a clean user-initiated one.
  • signal/signal_test.go: New test covering both cases — OS signal shutdown leaves RequestedShutdown() false; programmatic shutdown via RequestShutdown() sets it true.

Behaviour

Scenario Before After
User sends SIGINT / SIGTERM exit 0 ✅ exit 0 ✅
Health check triggers RequestShutdown() exit 0 ❌ exit 1 ✅

Test plan

  • go test ./signal/... passes
  • make install compiles cleanly
  • Manual test: run lnd with a short healthcheck interval, kill bitcoind, confirm lnd exits with code 1 (echo $?)

🤖 Generated with Claude Code

When lnd shuts itself down due to a health check failure (e.g. the chain
backend becomes unreachable), it previously exited with code 0. This caused
systemd and other process managers to treat the exit as intentional, so
Restart=on-failure would not trigger and the node would remain offline.

Add a requestedShutdown flag to Interceptor that is set atomically when
shutdown is triggered via RequestShutdown(), as opposed to an OS signal such
as SIGINT or SIGTERM. After lnd.Main() returns cleanly, main() checks the
flag and calls os.Exit(1) so that process managers can automatically restart
the daemon.

Fixes lightningnetwork#5625

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions github-actions Bot added the severity-medium Focused review required label Jul 1, 2026
@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown

🟡 PR Severity: MEDIUM

gh pr view | 3 files | 91 lines changed (25 lines / 2 files excluding tests)

🟡 Medium (2 files)
  • cmd/lnd/main.go - CLI entrypoint code under cmd/*; adds an os.Exit(1) call after a programmatic shutdown, does not touch core server logic
  • signal/signal.go - Not in a listed critical/high package; adds a requestedShutdown flag and RequestedShutdown() accessor to the Interceptor type
🟢 Low (1 file, excluded from count)
  • signal/signal_test.go - New test file only

Analysis

No files fall under the CRITICAL or HIGH package lists (lnwallet, htlcswitch, contractcourt, sweep, peer, keychain, input, channeldb, funding, lnwire, routing, invoices, discovery, graph, watchtower, feature, lnrpc, macaroons, etc.). cmd/lnd/main.go is CLI/entrypoint code and is classified MEDIUM per the rule that cmd/* does not inherit severity from similarly-named server-side packages. signal/signal.go doesn't map to any explicit category, so it falls to "Other Go files not categorized above" (MEDIUM).

No bump conditions apply: only 2 non-test files changed (well under 20) and 25 non-test lines changed (well under 500), and no multiple distinct critical packages are touched.

The change itself is low-risk in scope (adds a flag + exit code branch for process-manager compatibility on abnormal shutdown) but does touch the process shutdown path shared by all of lnd, so a focused review of the exit-code semantics and interaction with existing signal handling is still warranted — consistent with a MEDIUM classification.


To override, add a severity-override-{critical,high,medium,low} label.
<!-- pr-severity-bot -->

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

severity-medium Focused review required

Projects

None yet

Development

Successfully merging this pull request may close these issues.

lnd should exit with no-success error code when automatically shut down due to bitcoind problems

1 participant