[Fix] (P13 W5 S7): the verify read hook answers the monolith verb port's neutral-pack window from the applied pack, as for a server-stamped verb.

This commit is contained in:
2026-10-06 14:15:29 -04:00
parent 8efb7f492a
commit e0910ebd85
3 changed files with 30 additions and 1 deletions
+7 -1
View File
@@ -40,6 +40,9 @@
#include <MG_Pipe/PipeRoute.h>
#include <MG_Pipe/PipeMutation.h>
#include <Config.h>
#if MOBILEGL_BUILD_RECORD_ARM && MOBILEGL_PIPE_VERIFY
#include <MG_Impl/Pipe/Verb/VerbPort.h>
#endif
#if MOBILEGL_BUILD_DISAGGREGATED
// R-8 (c1): the client's liveness gates read the caps mirror, never MGPipeGetResourceOps().
@@ -689,7 +692,10 @@ namespace MobileGL::MG_Pipe {
const auto index = static_cast<SizeT>(field);
if (kMGPipeInputFieldSticky[index]) return;
#if MOBILEGL_BUILD_RECORD_ARM
if (self.ServerStampedVerb() && field == MGPipeInputField::GetPixelStoreParameters) {
// P13 W5: the monolith verb port applies records without a server stamp, and its readback
// forces the neutral pack around the backend's read exactly as the server's does.
if ((self.ServerStampedVerb() || MG_Record::MonolithPortApplyingForVerify()) &&
field == MGPipeInputField::GetPixelStoreParameters) {
// Compare the backend's pack field against the last payload applied to this
// context, including the neutral-pack override during readback. Never obtain
// the reference by reading the field being checked, or consult the client's
+15
View File
@@ -230,8 +230,19 @@ namespace MobileGL::MG_Record {
// still cuts a row wider than this, as it would for a slot).
constexpr Uint32 kMonolithMaxReplyBytes = 0x7fffffffu;
#if MOBILEGL_PIPE_VERIFY
thread_local Bool t_portApplying = false;
struct PortApplyingScope {
PortApplyingScope() { t_portApplying = true; }
~PortApplyingScope() { t_portApplying = false; }
};
#endif
Bool ApplyOnMonolithPort(MG_Pipe::MGPWireOp op, const void* payload, const MG_Pipe::MGPipeVerbTail* tails,
Uint32 tailCount, MG_Pipe::MGPipeReplySink* replies) {
#if MOBILEGL_PIPE_VERIFY
const PortApplyingScope applying;
#endif
RecordVerbSink& sink = MonolithVerbSink();
MG_Backend::BackendObject* backend = MG_Backend::pActiveBackendObject.get();
if (sink.Backend() != backend) {
@@ -1660,6 +1671,10 @@ namespace MobileGL::MG_Record {
void ArmVerbControlKnobs() { ArmControlKnobs(); }
#if MOBILEGL_PIPE_VERIFY
Bool MonolithPortApplyingForVerify() { return t_portApplying; }
#endif
void SetVerbSessionResolver(VerbSessionResolver resolver) { g_verbSessionResolver = resolver; }
void AssignVerbEmitters(MG_Backend::GlobalBackendFunctionsTable& table) {
+8
View File
@@ -58,6 +58,14 @@ namespace MobileGL::MG_Record {
// The E2 control's per-frame evidence line, emitted only while a control is armed.
void LogE2ControlLine(Uint64 frameOrdinal);
#if MOBILEGL_PIPE_VERIFY
// True while the monolith verb port applies a record on this thread. The verify read hook
// answers a pack-state read inside that window from the applied pack payload, as it does for a
// server-stamped verb: the record verb sink forces the neutral pack around its readback, so
// the live context is not the oracle there (PipeFill.cpp MGPipeVerifyReadHook).
Bool MonolithPortApplyingForVerify();
#endif
// Called by the Fatal slots. Named separately so a death test can filter on it and so
// that the message wording lives in exactly one place.
[[noreturn]] void UnmigratedVerbFatal(const char* slot);