viewtop: hang up after a reply instead of discovering it
The compositor answers one request per connection and returns. `connected` lags that close, so the 2 s poll's second tick wrote to a spent socket and died as PeerClosedError — once per shell start, 4 of 4 loads on 2026-08-13, while the same socket answered a hand-written request that second. The error also blamed reachability, which it never established; it now names the verb that was lost and how many were dropped behind it.
This commit is contained in:
parent
ef3a8513d1
commit
a8a4aac2d5
1 changed files with 30 additions and 4 deletions
|
|
@ -449,8 +449,16 @@ Singleton {
|
|||
const intent = (root._inflight && root._inflight.intent)
|
||||
|| (root._inflight && root._inflight.op) || "?";
|
||||
root.lastError = "viewtop socket unavailable";
|
||||
console.error("[viewtop-control] could not reach the compositor at "
|
||||
+ sock.path + " — the scene was NOT changed");
|
||||
// Name the verb and the count. The old wording claimed the
|
||||
// compositor could not be reached, which was the one thing it never
|
||||
// established — on 2026-08-13 this fired once per shell start while
|
||||
// viewtop answered a hand-written request on that same socket in
|
||||
// the same second. A transport error is not a diagnosis.
|
||||
console.error("[viewtop-control] " + intent + " was not delivered:"
|
||||
+ " the socket at " + sock.path + " closed with the request in"
|
||||
+ " flight" + (root._queue.length > 0
|
||||
? " (" + root._queue.length + " queued behind it dropped)"
|
||||
: ""));
|
||||
root._inflight = null;
|
||||
root._queue = [];
|
||||
root.refused(intent, root.lastError);
|
||||
|
|
@ -471,7 +479,10 @@ Singleton {
|
|||
console.error("[viewtop-control] unparseable reply: " + message);
|
||||
root.lastError = "unparseable reply";
|
||||
root.refused(intent, root.lastError);
|
||||
root._pump();
|
||||
if (sock.connected)
|
||||
sock.connected = false;
|
||||
else
|
||||
root._pump();
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -492,7 +503,22 @@ Singleton {
|
|||
root._ingest(reply);
|
||||
root.succeeded(intent);
|
||||
}
|
||||
root._pump();
|
||||
// Hang up rather than wait to discover we have been hung up on.
|
||||
//
|
||||
// `handle()` in control.rs answers one request and returns, so
|
||||
// the connection is spent the moment the reply is parsed. But
|
||||
// `connected` is this end's belief and it lags the peer's
|
||||
// close: measured 2026-08-13, the poll's second tick wrote to
|
||||
// the socket a full two seconds after the reply and the write
|
||||
// still went out, dying as PeerClosedError. That surfaced as
|
||||
// "could not reach the compositor" for a compositor that was
|
||||
// answering by hand at that same moment, and it cost the queued
|
||||
// verb. Closing here makes the next `_pump` start from a state
|
||||
// we set rather than one we inferred.
|
||||
if (sock.connected)
|
||||
sock.connected = false; // the disconnect handler re-pumps
|
||||
else
|
||||
root._pump();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue