| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
On 2026-06-04 cl restarted (autoheal, after its 15s healthcheck timed out),
and the app's waitanyinvoice long-poll hung on the now-dead listen socket.
listenerActive stayed true forever, so ensureListenerAlive never restarted
it, and incoming lightning payments stopped crediting for ~2h until a manual
app restart. The per-call RPC timeout in ln.ts can't catch this: waitanyinvoice
is intentionally in NO_TIMEOUT (it's meant to block).
Fix: ensureListenerAlive (runs every 120s) now also detects a stalled listener
— active but blocked in waitanyinvoice for >5min. It probes cl via the main
ln socket (getinfo); only if cl is actually alive does it treat the listen
socket as a zombie, call lnListen.reset() (new: drops the proxy's socket so the
next call reconnects), and re-arm. A listenerEpoch guard makes the wedged
invocation bow out when its waitanyinvoice finally rejects, so we never run two
listeners concurrently and never double-credit. Verified with a state-machine
test covering normal receive, quiet-but-healthy (left alone), stall+cl-alive
(recycled), stall+cl-down (left alone), and the no-double-listener race.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
A unix-domain RPC socket has no TCP keepalive, so if cl goes
unresponsive while the socket stays open (zombie/half-open), an awaited
call hangs forever — the "stuck spinner past /pay/bob, no error"
symptom. Nothing threw, so the existing reconnect-on-error path never
fired and only an app restart recovered it.
Wrap short-lived calls in a 30s Promise.race timeout (matching
health.ts). A timeout rejects with ETIMEDOUT, now part of isSocketDied,
so the client is dropped and the next call reconnects — no process
restart. Long-polls (waitanyinvoice et al), in-flight payments
(pay/xpay/sendpay/keysend), and bolt12 round-trips (fetchinvoice/
sendinvoice/offer) are exempt: timing those out client-side would risk
leaked debits or break intentional blocking.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
|