mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-11-15 14:03:23 +09:00
[MG_Remote] (P6/dl): a dying session names itself to the peer
Step three of CONTRACT-P6 5.2, the funnel's whole point: instead of the peer
reading a bare EOF and guessing, the session publishes a SessionFault frame
that names the family before it aborts.
THE WIRE CHANGE IS D2's, exactly: `table Fatal` appends `family: string`,
append-only, so an older peer still reads `code` and `message`. `code` stays
the coarse seven-value projection; `family` carries the full word.
SessionFail publishes it before the abort, on whichever session's control
plane is active - the client has a ClientSession, the server a ServerSession,
so under spawn the frame reaches the far side whichever role is dying. Under
inproc both exist and it goes to an in-process transport the aborting process
will never read, which is harmless and cheaper than a special case that would
then be the untested one. Best-effort by nature: this thread is about to die,
so a send that blocks or fails changes nothing.
seq/op from the prose are NOT threaded through the 90 sites: the message
already names the op where it matters, so the frame carries what it can name
honestly (code, family, message) rather than a field that is always zero.
The client recognizes it: RunRemoteSurfaceControlFrame's reply loop, which
already demuxes CapsSnapshot from SurfaceReply, gains a Fatal arm that logs the
family and detail, latches device-lost from it, and returns transport-closed.
A server that DETECTS a fatal condition and aborts itself now tells the client
why; a kill -9 still bypasses abort entirely and is caught by dl's hangup
witness instead - the two cover the two ways a server can die.
The census learns SessionFail: a SessionFail call, like a WireLogFatal call,
must carry a Fatal{ word in its string, so the enum and the string cannot
disagree. FatalFunnel.{h,cpp} join the funnel exemption. Baseline is 4 aborts.
FatalFamilyTest gains the wire round-trip: every family's frame carries its
word and its projected code across encode/verify/decode.
G1 re-measured after the schema change: 0 symbol diff, .text unchanged at
0xa52203. Unit 2359 (one pre-existing environmental failure), integration-split
186/186, integration-spawn 102/102, retrace 6/6, census 0 unmarked.
This commit is contained in:
@@ -1034,6 +1034,21 @@ namespace MobileGL::MG_Remote::Client {
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (envelope->msg_type() == ::MobileGL::Wire::CtrlMsg::Fatal) {
|
||||
// `dl` step three: the server published a SessionFault before it aborted, so this
|
||||
// is a death that NAMES ITSELF instead of arriving as a bare EOF. Log the family
|
||||
// and detail, latch device-lost from it, and report the op declined - the same
|
||||
// answer a hangup gives, now with a cause the guest's log can read.
|
||||
if (const auto* fatal = envelope->msg_as_Fatal()) {
|
||||
const char* fam = fatal->family() ? fatal->family()->c_str() : "<none>";
|
||||
const char* msg = fatal->message() ? fatal->message()->c_str() : "";
|
||||
MGLOG_E("MG_Remote client: the server published a SessionFault before dying - "
|
||||
"Fatal family %s: %s", fam, msg);
|
||||
}
|
||||
LatchDeviceLost("the server published a SessionFault and then aborted");
|
||||
frame.ok = false;
|
||||
return MOBILEGL_ERR_TRANSPORT_CLOSED;
|
||||
}
|
||||
if (envelope->msg_type() != ::MobileGL::Wire::CtrlMsg::SurfaceReply ||
|
||||
envelope->msg_as_SurfaceReply() == nullptr) {
|
||||
MGLOG_E("MG_Remote client: expected a SurfaceReply, got message type %d",
|
||||
|
||||
Reference in New Issue
Block a user