Follow-up to #138 / #137. The shutdown-interruptibility that #137 delivers has no automated regression guard.
Gap
tests/integration_spider.sh only verifies event propagation (kind-3 bootstrap → NIP-77 sync → live note), not that the process exits promptly when a shutdown is requested mid-bootstrap. A future change that reintroduces an elapsed-only or otherwise un-interruptible bootstrap loop would pass all existing tests while silently reintroducing the #138 SIGKILL hang.
Precedent
tests/integration_ws_idle_reclaim.sh (commit 2a5b86d) already establishes the pattern of a black-box integration test guarding a shutdown/lifecycle invariant that is invisible to unit tests.
Proposed test
Start the spider pointed at a slow or unreachable relay (e.g. a TCP listener that accepts but never completes the WebSocket/TLS handshake, or an unroutable address), then send SIGTERM during bootstrap and assert the process exits within a bounded time (well under the 60s StartOS grace). Fails CI if bootstrap ever again blocks thread.join().
Note: a fully un-interruptible connect window still exists until the connect-timeout work lands, so scope the initial test to the interruptible read-loop path (reachable-but-idle relay) to keep it deterministic.
Tracked internally as wisp-frw.
Follow-up to #138 / #137. The shutdown-interruptibility that #137 delivers has no automated regression guard.
Gap
tests/integration_spider.shonly verifies event propagation (kind-3 bootstrap → NIP-77 sync → live note), not that the process exits promptly when a shutdown is requested mid-bootstrap. A future change that reintroduces an elapsed-only or otherwise un-interruptible bootstrap loop would pass all existing tests while silently reintroducing the #138 SIGKILL hang.Precedent
tests/integration_ws_idle_reclaim.sh(commit 2a5b86d) already establishes the pattern of a black-box integration test guarding a shutdown/lifecycle invariant that is invisible to unit tests.Proposed test
Start the spider pointed at a slow or unreachable relay (e.g. a TCP listener that accepts but never completes the WebSocket/TLS handshake, or an unroutable address), then send
SIGTERMduring bootstrap and assert the process exits within a bounded time (well under the 60s StartOS grace). Fails CI if bootstrap ever again blocksthread.join().Note: a fully un-interruptible connect window still exists until the connect-timeout work lands, so scope the initial test to the interruptible read-loop path (reachable-but-idle relay) to keep it deterministic.
Tracked internally as
wisp-frw.