Skip to content

[DO NOT MERGE] Instrument __MonoMac_NSAsyncActionDispatcher for issue #25861#25919

Draft
rolfbjarne wants to merge 24 commits into
mainfrom
dev/rolf/issue-25861-instrumentation
Draft

[DO NOT MERGE] Instrument __MonoMac_NSAsyncActionDispatcher for issue #25861#25919
rolfbjarne wants to merge 24 commits into
mainfrom
dev/rolf/issue-25861-instrumentation

Conversation

@rolfbjarne

Copy link
Copy Markdown
Member

Throwaway diagnostic instrumentation to help reproduce and diagnose the GC/marshalling race in the flaky NSAsyncActionDispatcher failure.

The goal is to catch the failure on CI and learn:

  • Exactly where each __MonoMac_NSAsyncActionDispatcher is instantiated (creation stack trace), and whether it's always the same call site.
  • If/when the instance was disposed / garbage collected before the native callback ran.

How it works

  • New src/Foundation/NSAsyncDispatcherInstrumentation.cs: stores diagnostic data directly on the native Objective-C object via an associated reference (objc_setAssociatedObject), so it survives even after the managed instance is garbage collected.
  • NSAsyncDispatcher (in NSAction.cs) records the creation stack trace in its constructor, and logs lifecycle events (Apply, Dispose, finalize) as they happen.
  • MissingCtor (in Runtime.cs) reads this info from the still-alive native object and appends it to the marshalling exception message.

⚠️ This is throwaway instrumentation and must not be merged. It is only meant to gather data from CI.

Ref: #25861

🤖 Pull request created by Copilot

…25861

Add throwaway instrumentation to diagnose the GC/marshalling race in
#25861.

For every async dispatcher, record the creation stack trace and a log of
lifecycle events (Apply/Dispose/Finalize). This is stored directly on the
native Objective-C object via an associated reference, so it survives even
after the managed instance is garbage collected. When the marshalling
exception from the issue is raised (MissingCtor), this information is
appended to the error message.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@rolfbjarne rolfbjarne added the do-not-merge Do not merge this pull request label Jul 3, 2026
@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

… objc associated objects

The previous approach stored the diagnostic info on the native object via
objc_setAssociatedObject with OBJC_ASSOCIATION_RETAIN. Reading it back with
objc_getAssociatedObject deterministically segfaulted in objc_msgSend_uncached
on the normal Apply path, crashing every test that dispatches an async action.

Replace the objc-associated-object mechanism with a static managed dictionary
keyed by the native handle (IntPtr). This still survives GC of the managed
dispatcher instance (the key is the native pointer, the value is a string, so
it does not keep the managed object alive), but performs no Objective-C calls
and therefore cannot crash.

Verified: tests/linker "dont link" MacCatalyst now passes (9/9) instead of
segfaulting at startup.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

Copy link
Copy Markdown
Collaborator

✅ [PR Build #1f2ee77] Build passed (Detect API changes) ✅

Pipeline on Agent
Hash: 1f2ee7788349afe2bce1d67d9d9da25b5d9c13ae [PR build]

@vs-mobiletools-engineering-service2

Copy link
Copy Markdown
Collaborator

✅ [PR Build #1f2ee77] Build passed (Build macOS tests) ✅

Pipeline on Agent
Hash: 1f2ee7788349afe2bce1d67d9d9da25b5d9c13ae [PR build]

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

Copy link
Copy Markdown
Collaborator

🔥 [PR Build #9905d4b] Build failed (Build packages) 🔥

Build failed for the job 'Build packages' (with job status 'Failed')

Pipeline on Agent
Hash: 9905d4bcd5a0f69798b3f53fed32a8bf43bb09ce [PR build]

@vs-mobiletools-engineering-service2

Copy link
Copy Markdown
Collaborator

🔥 [CI Build #a1465a2] Test results 🔥

Test results

❌ Tests failed on VSTS: test results

2 tests crashed, 12 tests failed, 151 tests passed.

Failures

❌ dotnettests tests (iOS)

1 tests failed, 0 tests passed.

Failed tests

  • DotNet tests: Failed (Execution failed with exit code 1)
    • Xamarin.Tests.AppSizeTest.MonoVM_Interpreter(iOS,"ios-arm64"): Multiple failures or warnings in test:
  1. The app bundle's file list changed (added: 'System.Console.dll'). The updated expect...
    * Xamarin.Tests.AppSizeTest.MonoVM(iOS,"ios-arm64"): Multiple failures or warnings in test:
  2. The app bundle's file list changed (added: 'System.Console.aotdata.arm64', added: 'S...
    * Xamarin.Tests.AppSizeTest.NativeAOT_TrimmableStatic(iOS,"ios-arm...: App size changed significantly (+49,458 bytes (48.3 KB = 0.0 MB) different > tolerance of +-10,240 bytes (10.0 KB = 0.0 MB)). Ex...
    * ... and 1 more

Html Report (VSDrops) Download

❌ dotnettests tests (MacCatalyst)

1 tests failed, 0 tests passed.

Failed tests

  • DotNet tests: Failed (Execution failed with exit code 1)
    • Xamarin.Tests.AppSizeTest.MonoVM_Interpreter(MacCatalyst,"maccat...: Multiple failures or warnings in test:
  1. The app bundle's file list changed (added: 'Contents/MonoBundle/System.Console.dll')...
    * Xamarin.Tests.AppSizeTest.MonoVM(MacCatalyst,"maccatalyst-arm64"...: Multiple failures or warnings in test:
  2. The app bundle's file list changed (added: 'Contents/MonoBundle/System.Console.aotda...
    * Xamarin.Tests.AppSizeTest.NativeAOT_TrimmableStatic(MacCatalyst,...: App size changed significantly (+49,787 bytes (48.6 KB = 0.0 MB) different > tolerance of +-10,240 bytes (10.0 KB = 0.0 MB)). Ex...
    * ... and 1 more

Html Report (VSDrops) Download

❌ dotnettests tests (macOS)

1 tests failed, 0 tests passed.

Failed tests

  • DotNet tests: Failed (Execution failed with exit code 1)
    • Xamarin.Tests.AppSizeTest.CoreCLR_Interpreter_TrimmableStatic(Ma...: App size changed significantly (+10,474 bytes (10.2 KB = 0.0 MB) different > tolerance of +-10,240 bytes (10.0 KB = 0.0 MB)). Ex...
    • Xamarin.Tests.AppSizeTest.CoreCLR_Interpreter(MacOSX,"osx-arm64;...: App size changed significantly (+11,498 bytes (11.2 KB = 0.0 MB) different > tolerance of +-10,240 bytes (10.0 KB = 0.0 MB)). Ex...
    • Xamarin.Tests.AppSizeTest.NativeAOT_TrimmableStatic(MacOSX,"osx-...: App size changed significantly (+942,378 bytes (920.3 KB = 0.9 MB) different > tolerance of +-10,240 bytes (10.0 KB = 0.0 MB)). ...
    • ... and 1 more

Html Report (VSDrops) Download

❌ dotnettests tests (tvOS)

1 tests failed, 0 tests passed.

Failed tests

  • DotNet tests: Failed (Execution failed with exit code 1)
    • Xamarin.Tests.AppSizeTest.MonoVM_Interpreter(TVOS,"tvos-arm64"): Multiple failures or warnings in test:
  1. The app bundle's file list changed (added: 'System.Console.dll'). The updated expect...
    * Xamarin.Tests.AppSizeTest.MonoVM(TVOS,"tvos-arm64"): Multiple failures or warnings in test:
  2. The app bundle's file list changed (added: 'System.Console.aotdata.arm64', added: 'S...
    * Xamarin.Tests.AppSizeTest.NativeAOT_TrimmableStatic(TVOS,"tvos-a...: App size changed significantly (+65,834 bytes (64.3 KB = 0.1 MB) different > tolerance of +-10,240 bytes (10.0 KB = 0.0 MB)). Ex...
    * ... and 1 more

Html Report (VSDrops) Download

❌ monotouch tests (iOS)

3 tests failed, 15 tests passed.

Failed tests

  • monotouch-test/iOS - simulator/Debug: Failed
  • monotouch-test/iOS - simulator/Debug (PrepareAssemblies): Failed
  • monotouch-test/iOS - simulator/Release (managed static registrar, all optimizations): Failed

Html Report (VSDrops) Download

❌ monotouch tests (MacCatalyst)

1 tests failed, 16 tests passed.

Failed tests

  • monotouch-test/Mac Catalyst/Debug (PrepareAssemblies): TimedOut (Execution timed out after 1200 seconds.
    Test run crashed)

Html Report (VSDrops) Download

❌ monotouch tests (macOS)

🔥 Failed catastrophically on VSTS: test results - monotouch_macos (no summary found).

Html Report (VSDrops) Download

❌ monotouch tests (tvOS)

🔥 Failed catastrophically on VSTS: test results - monotouch_tvos (no summary found).

Html Report (VSDrops) Download

❌ Tests on macOS Monterey (12) tests

1 tests failed, 4 tests passed.

Failed tests

  • MacCatalyst/maccatalyst-arm64 monotouch-test: Failed (exit code 134)
    • No test failure details available. Output tail:
      • at Foundation.NSAsyncActionDispatcher:Apply <0x00047>
      • at System.Object:runtime_invoke_dynamic <0x00127>
      • at <unknown> <0xffffffff>
      • at UIKit.UIApplication:xamarin_UIApplicationMain <0x00007>
      • at UIKit.UIApplication:UIApplicationMain <0x00063>
      • at UIKit.UIApplication:Main <0x00147>
      • at MainClass:Main <0x00097>
      • at System.Object:runtime_invoke_dynamic <0x00127>
      • =================================================================
      • Execution completed with exit code 134

Html Report (VSDrops) Download

❌ Tests on macOS Ventura (13) tests

1 tests failed, 4 tests passed.

Failed tests

  • macOS/osx-arm64 monotouch-test: Failed (exit code 137)
    • No test failure details available. Output tail:
      • 2026-07-08 16:41:38.138 monotouchtest[53903:102705046] IAPAppConnectedAccessories: __eaClientHasCheckedForConnectedAccessories 0 -> 1
      • 2026-07-08 16:41:38.138 monotouchtest[53903:102705046] IAPAppConnectedAccessories: IAPDHasLaunched 0, IAP2DHasLaunched 0
      • 2026-07-08 16:41:38.138 monotouchtest[53903:102705046] [#ExternalAccessory] Returning connectedAccessories count 0
      • [PASS] Shared
      • MonoTouchFixtures.ExternalAccessory.AccessoryManagerTest : 1.6685 ms
      • MonoTouchFixtures.ExternalAccessory : 1.6814 ms
      • MonoTouchFixtures.Foundation
      • MonoTouchFixtures.Foundation.AsyncDispatcherStressTest
      • Execution timed out after 600 seconds.
      • Execution completed with exit code 137
  • MacCatalyst/maccatalyst-arm64 monotouch-test: Failed (exit code 134)
    • No test failure details available. Output tail:
      • at Foundation.NSAsyncActionDispatcher:Apply <0x00047>
      • at System.Object:runtime_invoke_dynamic <0x00127>
      • at <unknown> <0xffffffff>
      • at UIKit.UIApplication:xamarin_UIApplicationMain <0x00007>
      • at UIKit.UIApplication:UIApplicationMain <0x00063>
      • at UIKit.UIApplication:Main <0x00147>
      • at MainClass:Main <0x00097>
      • at System.Object:runtime_invoke_dynamic <0x00127>
      • =================================================================
      • Execution completed with exit code 134

Html Report (VSDrops) Download

❌ Tests on macOS Sequoia (15) tests

1 tests failed, 4 tests passed.

Failed tests

  • macOS/osx-arm64 monotouch-test: Failed (exit code 137)
    • No test failure details available. Output tail:
      • 2026-07-08 16:45:00.791 monotouchtest[1982:125947195] IAPAppConnectedAccessories: __eaClientHasCheckedForConnectedAccessories 0 -> 1
      • 2026-07-08 16:45:00.791 monotouchtest[1982:125947195] IAPAppConnectedAccessories: IAPDHasLaunched 0, IAP2DHasLaunched 0
      • 2026-07-08 16:45:00.792 monotouchtest[1982:125947195] [#ExternalAccessory] Returning connectedAccessories count 0
      • [PASS] Shared
      • MonoTouchFixtures.ExternalAccessory.AccessoryManagerTest : 2.624 ms
      • MonoTouchFixtures.ExternalAccessory : 2.636 ms
      • MonoTouchFixtures.Foundation
      • MonoTouchFixtures.Foundation.AsyncDispatcherStressTest
      • Execution timed out after 600 seconds.
      • Execution completed with exit code 137

Html Report (VSDrops) Download

❌ Tests on macOS Tahoe (26) tests

1 tests failed, 4 tests passed.

Failed tests

  • macOS/osx-arm64 monotouch-test: Failed (exit code 137)
    • No test failure details available. Output tail:
      • 2026-07-08 16:38:24.230 monotouchtest[59944:1019916] IAPAppConnectedAccessories: __eaClientHasCheckedForConnectedAccessories 0 -> 1
      • 2026-07-08 16:38:24.230 monotouchtest[59944:1019916] IAPAppConnectedAccessories: IAPDHasLaunched 0, IAP2DHasLaunched 0
      • 2026-07-08 16:38:24.230 monotouchtest[59944:1019916] [#ExternalAccessory] Returning connectedAccessories count 0
      • [PASS] Shared
      • MonoTouchFixtures.ExternalAccessory.AccessoryManagerTest : 2.7515 ms
      • MonoTouchFixtures.ExternalAccessory : 2.7669 ms
      • MonoTouchFixtures.Foundation
      • MonoTouchFixtures.Foundation.AsyncDispatcherStressTest
      • Execution timed out after 600 seconds.
      • Execution completed with exit code 137
  • MacCatalyst/maccatalyst-arm64 monotouch-test: Failed (exit code 134)
    • No test failure details available. Output tail:
      • at Foundation.NSAsyncActionDispatcher:Apply <0x00047>
      • at System.Object:runtime_invoke_dynamic <0x00127>
      • at <unknown> <0xffffffff>
      • at UIKit.UIApplication:xamarin_UIApplicationMain <0x00007>
      • at UIKit.UIApplication:UIApplicationMain <0x00063>
      • at UIKit.UIApplication:Main <0x00147>
      • at MainClass:Main <0x00097>
      • at System.Object:runtime_invoke_dynamic <0x00127>
      • =================================================================
      • Execution completed with exit code 134

Html Report (VSDrops) Download

Successes

✅ assembly-processing: All 1 tests passed. Html Report (VSDrops) Download
✅ cecil: All 1 tests passed. Html Report (VSDrops) Download
✅ dotnettests (Multiple platforms): All 1 tests passed. Html Report (VSDrops) Download
✅ framework: All 2 tests passed. Html Report (VSDrops) Download
✅ fsharp: All 4 tests passed. Html Report (VSDrops) Download
✅ generator: All 5 tests passed. Html Report (VSDrops) Download
✅ interdependent-binding-projects: All 4 tests passed. Html Report (VSDrops) Download
✅ introspection: All 4 tests passed. Html Report (VSDrops) Download
✅ linker (iOS): All 15 tests passed. Html Report (VSDrops) Download
✅ linker (MacCatalyst): All 15 tests passed. Html Report (VSDrops) Download
✅ linker (macOS): All 21 tests passed. Html Report (VSDrops) Download
✅ linker (tvOS): All 15 tests passed. Html Report (VSDrops) Download
✅ msbuild: All 2 tests passed. Html Report (VSDrops) Download
✅ sharpie: All 1 tests passed. Html Report (VSDrops) Download
✅ windows: All 3 tests passed. Html Report (VSDrops) Download
✅ xcframework: All 4 tests passed. Html Report (VSDrops) Download
✅ xtro: All 1 tests passed. Html Report (VSDrops) Download

macOS tests

✅ Tests on macOS Sonoma (14): All 5 tests passed. Html Report (VSDrops) Download

Linux Build Verification

Linux build succeeded

Pipeline on Agent
Hash: a1465a2cdc5a9bdc9f1f9ebcb14e87b7716b2dbc [PR build]

…er (issue #25861)

Throwaway instrumentation (DO NOT MERGE): add per-handle logging of
object_map mutations for __MonoMac_NSAsyncActionDispatcher instances.

* When an NSAsyncActionDispatcher is added to or removed from object_map,
  print a single greppable "#25861# ... OBJMAP" line to stdout, and store
  the current stack trace (keyed on the native handle) so all object_map
  activity for a given handle is dumped when the marshalling exception
  (8027/8034) is raised.
* The add is logged in Runtime.RegisterNSObject (which runs during native
  NSObject construction, before RecordCreation), keyed on the managed type;
  removes are logged at the actual object_map.Remove sites in
  UnregisterNSObject/NativeObjectHasDied/RemoveFromObjectMap, keyed on the
  tracked-handle set.
* Restrict all tracking/logging to NSAsyncActionDispatcher only (skip other
  NSAsyncDispatcher subclasses such as the synchronization-context
  dispatcher) to keep the logs small.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@vs-mobiletools-engineering-service2

Copy link
Copy Markdown
Collaborator

✅ API diff for current PR / commit

NET (empty diffs)

✅ API diff vs stable

NET (empty diffs)

ℹ️ Generator diff

Generator Diff: vsdrops (html) vsdrops (raw diff) gist (raw diff) - Please review changes)

Pipeline on Agent
Hash: 55eddcc20a107ae8722e3994026587133e9fbbd6 [PR build]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

copilot do-not-merge Do not merge this pull request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants