Repository navigation
Mitigation: no Regex on the first managed report (Mono GC crash trigger) - #271
Conversation
…ten parsing.
ManagedAddressPairing and ManagedSignatureRecipe built four Regex objects (three
distinct patterns) in static constructors, so the first managed exception report
constructed them. On Unity 2021.3.45f1 Mono (ARMv7 Android) the stack of a SIGSEGV in
libmonobdwgc GC_mark_from (2 of 28 fresh-install cold starts) showed that Regex
construction running when the fault happened. New ManagedFrameLocation parses the
same three shapes (" in FILE:LINE", "(at FILE:LINE)", "libX.so") with no Regex.
Behaviour is unchanged: the host tests keep the original patterns as the reference and
compare over real device frames, handwritten edge cases and 200k generated inputs, and
pin the \s / \d assumptions over all 65,536 chars.
Mitigation only: removes this allocation burst from the first report; the suspected
runtime defect is not fixed.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SfQe6YfjwEeceEeuf3jS6x
|
Warning Review limit reachedYou've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Next included review available in 10 minutes. View limit details
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. CodeRabbit Verify
|
|
Claude finished @krassx's task in 1m 32s —— View job Review of PR #271: no Regex on the first managed report
No bugs found, so there are no inline comments. What I checkedEquivalence of
What I ran
Other Regex use
Minor, non-blocking observations
Summary
|
There was a problem hiding this comment.
Deep review (HEAD 2db1cc8)
Intent: Mitigation, not a Mono GC fix. On Unity 2021.3.45f1 Mono ARMv7, 2 of 28 fresh-install cold starts died in GC_mark_from while the first managed report constructed Regex objects (RegexCharClass:.cctor ← Regex:.ctor ← ManagedAddressPairing:.cctor ← ExceptionPipeline.Report). This replaces those four objects (three patterns) with ManagedFrameLocation.
Checked against the surrounding path, not just the diff. ManagedFrameAssembly.FrameLines already touches ManagedAddressPairing on Mono (where Pair is skipped because there are no native IPs), so the old type initializer ran on the first report even without pairing. FromException then hits ManagedSignatureRecipe.Compute → TryFileLine / IsEngineFrame. Production frames are Split+Trim’d first (StackLines), so the parsers see single-line text. HasSourceLocation still only recognizes in FILE:LINE (same as the old regex); (at FILE:LINE) remains signature-only. No other new Regex remains on the player report path (Runtime/Internal has none).
Adversarial cases walked: leftmost in / (at , greedy file, last :digits, . not crossing , \s+ leaving one file character, lib*.so with a non-[A-Za-z0-9_] lookahead, truncated logcat lines, in <hash>:0, extra ), libfoo.sox vs libunity.so(+0x…). The host tests keep the original three patterns as the oracle (handwritten edges, 377-line device corpus, 200k generated strings plus a frame-shaped grid, and \s/\d vs char.IsWhiteSpace/char.IsDigit over all 65,536 BMP chars).
Findings
No P0–P3 issues. Equivalence holds for the production shapes; the first-report type initializer that constructed Regex is gone.
Residual (already disclosed, not a defect of this PR)
SHA256.Create(),new StackTrace(false).ToString(), firstException.StackTraceformatting, and JIT still run on the first report. Warming the signature path at launch (next toWarmModuleUuid) is a separate device loop.- 0 SIGSEGV in 41 post-change cold starts is only suggestive at a ~7% prior rate (the changelog already says this).
CI
Observed on this SHA, not run locally (dotnet is not on PATH): Unity C# compile, wrapper-policy tests (2144 passed / 32 skipped), wrapper-policy macOS iOS scripts, Android wrapper, Windows Editor, iOS bridge, CodeQL — all SUCCESS.
- Overall risk: Low
- Merge recommendation: Approve
- Most important issues to fix: None
- Positive: Honest mitigation framing; the old patterns are kept as a live oracle rather than deleted; no public API change; parsers are allocation-bounded and have no shared mutable state.
Sent by Cursor Automation: Bugsee code review


What
ManagedAddressPairingandManagedSignatureRecipebuilt fourRegexobjects (three distinct patterns) in static constructors, so the first managed exception report constructed them. They are replaced by hand-written parsers in the newManagedFrameLocation(" in FILE:LINE","(at FILE:LINE)","libX.so"), with the same results. No public API change.Why
On Unity 2021.3.45f1 Mono (ARMv7 Android, HONOR WOD-LX1) a SIGSEGV in libmonobdwgc
GC_mark_fromwas seen in 2 of 28 fresh-install cold starts (plus one earlier one-off). The managed stack of all 3 crashes:RegexCharClass:.cctor <- Regex:.ctor <- ManagedAddressPairing:.cctor <- ManagedExceptionPayload.FromException <- ExceptionPipeline.Report <- LogException. The suspected cause is a Mono/Boehm GC defect; the SDK's first report is where it was triggered. This PR removes the Regex construction from that first report.This is a mitigation, not a fix. The suspected runtime defect is not addressed.
Equivalence evidence
HasSourceLocation,TryFileLine,IsEngineFrame): real device frames (Mono Release/Development, dev matrix, Unity-log(at ...)lines and nativelib*.solines), about 80 handwritten edge cases, 200k generated strings plus a frame-shaped grid, and the\s/\dvschar.IsWhiteSpace/char.IsDigitassumption over all 65,536 chars.dotnet testinTests~/WrapperPolicy: 2176 passed.compile-check.shok.Device evidence
Unity 2021.3.45f1 Mono Release build with this change, fresh install before every cold start, BugseeMiniGame +
lx_scn main-syncprobe, same flow as the sessions that reproduced the crash: 0 SIGSEGV in 41 valid runs (earlier: 2 of 28 fresh-install runs). Two further runs died at the Android 15 32-bit ABI dialog before Unity started and are excluded. Reports still reach staging AU (AU-246, frames in the usual form).Statistics caveat: if the true rate were still about 7%, P(0 of 41) is about 5%, so 0/41 is only suggestive, not conclusive.
Known residual risk / possible follow-up (not in this PR)
Other first-use initialisations remain on the first-report path:
SHA256.Create()inManagedSignatureRecipe(CryptoConfig first use),new StackTrace(false).ToString()inManagedExceptionPayload, the firstException.StackTraceformatting, and JIT. A possible follow-up is warming the signature path at launch next toWarmModuleUuid; it needs its own device loop.🤖 Generated with Claude Code
https://claude.ai/code/session_01SfQe6YfjwEeceEeuf3jS6x