bin.js: exit on dead sbot connection instead of wedging
ssb-viewer holds one muxrpc handle captured in a closure and has no reconnect path. When sbot is OOM-killed and restarted by run-server.sh, the viewer kept port 8807 open while holding a dead connection and never answered again -- the silent wedge. Listen for muxrpc closed and exit(1) so the while-loop in run-ssb-viewer.sh restarts with a fresh connection. Also poll whoami to catch half-open connections where closed never fires. Verified: killing sbot now self-heals in ~4s instead of hanging.
This commit is contained in:
@@ -1,6 +1,49 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
// ssb-viewer connects to sbot exactly once and hands the handle to index.js,
|
||||
// which captures it in a closure behind http.createServer().listen(). There is
|
||||
// no reconnect. So when sbot dies -- which on this box means "gets OOM-killed",
|
||||
// after which run-server.sh restarts it -- the viewer keeps port 8807 open
|
||||
// while holding a dead muxrpc connection, and never answers another request.
|
||||
//
|
||||
// That is the silent wedge. The fix is not to reconnect (index.js can't take a
|
||||
// new handle) but to exit loudly, so the `while true` loop in run-ssb-viewer.sh
|
||||
// restarts us with a fresh connection.
|
||||
|
||||
var PING_INTERVAL_MS = 60000
|
||||
var PING_TIMEOUT_MS = 20000
|
||||
|
||||
function bail (why) {
|
||||
console.error('[viewer] ' + new Date().toISOString() + ' ' + why + ' — exiting so the run loop restarts us')
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
require('ssb-client')(function (err, sbot, config) {
|
||||
if (err) throw err
|
||||
// ssb-client already wraps this as "could not connect to sbot", so don't
|
||||
// prefix it again.
|
||||
if (err) return bail(String(err.message || err))
|
||||
|
||||
// muxrpc emits 'closed' when the underlying stream ends
|
||||
// (see node_modules/muxrpc/index.js). This is the fast path.
|
||||
sbot.on('closed', function () {
|
||||
bail('sbot connection closed')
|
||||
})
|
||||
|
||||
// Belt and braces: a half-open TCP connection can leave 'closed' unfired
|
||||
// while calls silently hang forever. Poll a cheap RPC to catch that case.
|
||||
if (typeof sbot.whoami === 'function') {
|
||||
var timer = setInterval(function () {
|
||||
var timeout = setTimeout(function () {
|
||||
bail('sbot did not answer whoami within ' + (PING_TIMEOUT_MS / 1000) + 's')
|
||||
}, PING_TIMEOUT_MS)
|
||||
sbot.whoami(function (err) {
|
||||
clearTimeout(timeout)
|
||||
if (err) bail('sbot whoami failed: ' + (err.message || err))
|
||||
})
|
||||
}, PING_INTERVAL_MS)
|
||||
// Don't hold the event loop open on our account.
|
||||
timer.unref()
|
||||
}
|
||||
|
||||
require('.').init(sbot, config)
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user