[iOS] Fix ObjectDisposedException in ContentView.RemoveContentMask#34680
[iOS] Fix ObjectDisposedException in ContentView.RemoveContentMask#34680Oxymoron290 wants to merge 7 commits intodotnet:mainfrom
Conversation
Check Handle != IntPtr.Zero before calling RemoveFromSuperLayer() on _contentMask to prevent ObjectDisposedException when iOS has already deallocated the underlying CAShapeLayer during view hierarchy teardown. This follows the established disposal guard pattern used throughout the codebase (ViewRenderer.cs, LayoutFactory2.cs, CellRenderer.cs, etc.). Fixes a crash reported in Active Trader Pro on iOS/MacCatalyst where WillRemoveSubview triggers RemoveContentMask after the native layer has been collected. Related: dotnet#30861, dotnet#33818 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 34680Or
iex "& { $(irm https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 34680" |
There was a problem hiding this comment.
Pull request overview
Fixes an iOS/MacCatalyst ObjectDisposedException when tearing down ContentView by guarding RemoveContentMask() against invoking RemoveFromSuperLayer() on a disposed CAShapeLayer.
Changes:
- Add a native-handle guard before removing the
_contentMasklayer from its superlayer. - Add an iOS device regression test that simulates native mask deallocation and asserts removal does not throw.
- Add minimal clip/shape stubs to force mask creation during the test.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| src/Core/src/Platform/iOS/ContentView.cs | Adds a Handle != IntPtr.Zero guard before calling RemoveFromSuperLayer() on _contentMask. |
| src/Core/tests/DeviceTests/Handlers/ContentView/ContentViewTests.iOS.cs | Adds a device regression test and local stubs to reproduce the disposed-mask scenario. |
src/Core/tests/DeviceTests/Handlers/ContentView/ContentViewTests.iOS.cs
Outdated
Show resolved
Hide resolved
| public Paint Stroke { get; set; } | ||
| public double StrokeThickness { get; set; } = 1; | ||
| public LineCap StrokeLineCap { get; set; } | ||
| public LineJoin StrokeLineJoin { get; set; } | ||
| public float[] StrokeDashPattern { get; set; } |
There was a problem hiding this comment.
This stub introduces non-nullable reference-type properties (Paint Stroke and float[] StrokeDashPattern) without initialization, which can produce nullable-analysis warnings (and may fail builds if warnings are treated as errors). Initialize them to safe defaults or mark them nullable (e.g., Paint? / float[]?) to keep the test project warning-clean.
| public Paint Stroke { get; set; } | |
| public double StrokeThickness { get; set; } = 1; | |
| public LineCap StrokeLineCap { get; set; } | |
| public LineJoin StrokeLineJoin { get; set; } | |
| public float[] StrokeDashPattern { get; set; } | |
| public Paint? Stroke { get; set; } | |
| public double StrokeThickness { get; set; } = 1; | |
| public LineCap StrokeLineCap { get; set; } | |
| public LineJoin StrokeLineJoin { get; set; } | |
| public float[]? StrokeDashPattern { get; set; } |
- Replace conditional mask disposal with Assert.IsType<CAShapeLayer> to fail fast if the mask is not created (avoids false-positive) - Assert Handle == IntPtr.Zero after disposal to verify test setup - Remove customer issue link from test comment - Add reference to upstream dotnet/macios#10562 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
/azp run maui-pr-uitests, maui-pr-devicetests |
|
Azure Pipelines successfully started running 2 pipeline(s). |
Assert.IsType<CAShapeLayer> requires an exact type match, but _contentMask is typed as StaticCAShapeLayer (a subclass of CAShapeLayer). This caused the RemoveContentMaskDoesNotThrowWhenDisposed test to fail on iOS and MacCatalyst with: 'Assert.IsType() Failure: Value is not the exact type' Also improve Assert.True to Assert.Equal for better diagnostic output on failure. Fixes: net10.0 iOS/MacCatalyst Helix Tests (Mono) device test failures Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
/azp run maui-pr-devicetests |
|
Azure Pipelines successfully started running 1 pipeline(s). |
…ison Assert.Equal(IntPtr.Zero, mask.Handle) fails on Apple TFMs because mask.Handle returns nint (NativeHandle) and xUnit's overload resolution falls through to Assert.Equal<DateTime>, producing CS1503. Use Assert.True with equality check instead. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
/azp run maui-pr-devicetests |
|
Azure Pipelines successfully started running 1 pipeline(s). |
On real iOS/MacCatalyst devices, calling Dispose() on a CAShapeLayer does not zero its Handle while another native reference (Layer.Mask) still retains it. Clear the native reference first to properly simulate iOS deallocating the layer during view teardown. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
With content.Layer.Mask cleared before Dispose(), the native retain count drops to zero and Handle is properly zeroed. Re-add the assertion to verify the guard condition is actually being tested. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Instead of relying on platform-specific Dispose() behavior (which varies depending on native retain counts), create a fresh CAShapeLayer with no native retains, Dispose it (deterministically zeroing Handle), then inject it into the private _contentMask field via reflection. This guarantees Handle == IntPtr.Zero on all platforms and directly tests the production guard in RemoveContentMask(). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
/azp run maui-pr-uitests, maui-pr-devicetests |
|
Azure Pipelines successfully started running 2 pipeline(s). |
|
/backport to release/10.0.1xx-sr3 |
|
Started backporting to |
🚦 Gate - Test Before and After Fix📊 Expand Full Gate —
|
| Test | Without Fix (expect FAIL) | With Fix (expect PASS) |
|---|---|---|
📱 ContentViewTests (RemoveContentMaskDoesNotThrowWhenDisposed) Category=ContentView |
❌ PASS — 411s | ✅ PASS — 204s |
🔴 Without fix — 📱 ContentViewTests (RemoveContentMaskDoesNotThrowWhenDisposed): PASS ❌ · 411s
(truncated to last 15,000 chars)
frame #7: 0x000000018dce0c78 Foundation`-[NSRunLoop(NSRunLoop) runMode:beforeDate:] + 212
�[40m�[37mdbug�[39m�[22m�[49m: frame #8: 0x000000018dd543a4 Foundation`-[NSRunLoop(NSRunLoop) runUntilDate:] + 100
�[40m�[37mdbug�[39m�[22m�[49m: frame #9: 0x0000000102eb2f28 mlaunch`xamarin_dyn_objc_msgSend + 160
�[40m�[37mdbug�[39m�[22m�[49m: frame #10: 0x000000010654e15c
�[40m�[37mdbug�[39m�[22m�[49m: frame #11: 0x00000001068b1ee8
�[40m�[37mdbug�[39m�[22m�[49m: frame #12: 0x00000001065477a4
�[40m�[37mdbug�[39m�[22m�[49m: frame #13: 0x00000001064e10b4
�[40m�[37mdbug�[39m�[22m�[49m: frame #14: 0x0000000105cfcd54
�[40m�[37mdbug�[39m�[22m�[49m: frame #15: 0x0000000104bbcc04 libcoreclr.dylib`CallDescrWorkerInternal + 132
�[40m�[37mdbug�[39m�[22m�[49m: frame #16: 0x0000000104a3ad30 libcoreclr.dylib`MethodDescCallSite::CallTargetWorker(unsigned long long const*, unsigned long long*, int) + 836
�[40m�[37mdbug�[39m�[22m�[49m: frame #17: 0x0000000104941350 libcoreclr.dylib`RunMain(MethodDesc*, short, int*, PtrArray**) + 648
�[40m�[37mdbug�[39m�[22m�[49m: frame #18: 0x0000000104941688 libcoreclr.dylib`Assembly::ExecuteMainMethod(PtrArray**, int) + 264
�[40m�[37mdbug�[39m�[22m�[49m: frame #19: 0x000000010496929c libcoreclr.dylib`CorHost2::ExecuteAssembly(unsigned int, char16_t const*, int, char16_t const**, unsigned int*) + 640
�[40m�[37mdbug�[39m�[22m�[49m: frame #20: 0x000000010492f650 libcoreclr.dylib`coreclr_execute_assembly + 232
�[40m�[37mdbug�[39m�[22m�[49m: frame #21: 0x0000000102eae140 mlaunch`mono_jit_exec + 204
�[40m�[37mdbug�[39m�[22m�[49m: frame #22: 0x0000000102eb1ecc mlaunch`xamarin_main + 884
�[40m�[37mdbug�[39m�[22m�[49m: frame #23: 0x0000000102eb31f4 mlaunch`main + 64
�[40m�[37mdbug�[39m�[22m�[49m: frame #24: 0x000000018c286b98 dyld`start + 6076
�[40m�[37mdbug�[39m�[22m�[49m: thread #2
�[40m�[37mdbug�[39m�[22m�[49m: frame #0: 0x000000018c5e5c34 libsystem_kernel.dylib`mach_msg2_trap + 8
�[40m�[37mdbug�[39m�[22m�[49m: frame #1: 0x000000018c5f83a0 libsystem_kernel.dylib`mach_msg2_internal + 76
�[40m�[37mdbug�[39m�[22m�[49m: frame #2: 0x000000018c5ee764 libsystem_kernel.dylib`mach_msg_overwrite + 484
�[40m�[37mdbug�[39m�[22m�[49m: frame #3: 0x000000018c5e5fa8 libsystem_kernel.dylib`mach_msg + 24
�[40m�[37mdbug�[39m�[22m�[49m: frame #4: 0x000000010492d2f4 libcoreclr.dylib`MachMessage::Receive(unsigned int) + 80
�[40m�[37mdbug�[39m�[22m�[49m: frame #5: 0x000000010492c61c libcoreclr.dylib`SEHExceptionThread(void*) + 164
�[40m�[37mdbug�[39m�[22m�[49m: frame #6: 0x000000018c627bc8 libsystem_pthread.dylib`_pthread_start + 136
�[40m�[37mdbug�[39m�[22m�[49m: thread #3, name = '.NET SynchManager'
�[40m�[37mdbug�[39m�[22m�[49m: frame #0: 0x000000018c5ebd04 libsystem_kernel.dylib`kevent + 8
�[40m�[37mdbug�[39m�[22m�[49m: frame #1: 0x0000000104921304 libcoreclr.dylib`CorUnix::CPalSynchronizationManager::ReadBytesFromProcessPipe(int, unsigned char*, int) + 484
�[40m�[37mdbug�[39m�[22m�[49m: frame #2: 0x00000001049209f0 libcoreclr.dylib`CorUnix::CPalSynchronizationManager::WorkerThread(void*) + 164
�[40m�[37mdbug�[39m�[22m�[49m: frame #3: 0x000000010492a0fc libcoreclr.dylib`CorUnix::CPalThread::ThreadEntry(void*) + 364
�[40m�[37mdbug�[39m�[22m�[49m: frame #4: 0x000000018c627bc8 libsystem_pthread.dylib`_pthread_start + 136
�[40m�[37mdbug�[39m�[22m�[49m: thread #4, name = '.NET EventPipe'
�[40m�[37mdbug�[39m�[22m�[49m: frame #0: 0x000000018c5ee498 libsystem_kernel.dylib`poll + 8
�[40m�[37mdbug�[39m�[22m�[49m: frame #1: 0x0000000104c1ce90 libcoreclr.dylib`ds_ipc_poll(_DiagnosticsIpcPollHandle*, unsigned long, unsigned int, void (*)(char const*, unsigned int)) + 172
�[40m�[37mdbug�[39m�[22m�[49m: frame #2: 0x0000000104ccabb0 libcoreclr.dylib`ds_ipc_stream_factory_get_next_available_stream(void (*)(char const*, unsigned int)) + 756
�[40m�[37mdbug�[39m�[22m�[49m: frame #3: 0x0000000104cc8a68 libcoreclr.dylib`server_thread(void*) + 372
�[40m�[37mdbug�[39m�[22m�[49m: frame #4: 0x000000010492a0fc libcoreclr.dylib`CorUnix::CPalThread::ThreadEntry(void*) + 364
�[40m�[37mdbug�[39m�[22m�[49m: frame #5: 0x000000018c627bc8 libsystem_pthread.dylib`_pthread_start + 136
�[40m�[37mdbug�[39m�[22m�[49m: thread #5, name = '.NET DebugPipe'
�[40m�[37mdbug�[39m�[22m�[49m: frame #0: 0x000000018c5e6678 libsystem_kernel.dylib`__open + 8
�[40m�[37mdbug�[39m�[22m�[49m: frame #1: 0x000000018c5f16a4 libsystem_kernel.dylib`open + 64
�[40m�[37mdbug�[39m�[22m�[49m: frame #2: 0x0000000104c1da84 libcoreclr.dylib`TwoWayPipe::WaitForConnection() + 40
�[40m�[37mdbug�[39m�[22m�[49m: frame #3: 0x0000000104c18578 libcoreclr.dylib`DbgTransportSession::TransportWorker() + 232
�[40m�[37mdbug�[39m�[22m�[49m: frame #4: 0x0000000104c175c8 libcoreclr.dylib`DbgTransportSession::TransportWorkerStatic(void*) + 40
�[40m�[37mdbug�[39m�[22m�[49m: frame #5: 0x000000010492a0fc libcoreclr.dylib`CorUnix::CPalThread::ThreadEntry(void*) + 364
�[40m�[37mdbug�[39m�[22m�[49m: frame #6: 0x000000018c627bc8 libsystem_pthread.dylib`_pthread_start + 136
�[40m�[37mdbug�[39m�[22m�[49m: thread #6, name = '.NET Debugger'
�[40m�[37mdbug�[39m�[22m�[49m: frame #0: 0x000000018c5e93cc libsystem_kernel.dylib`__psynch_cvwait + 8
�[40m�[37mdbug�[39m�[22m�[49m: frame #1: 0x000000018c62809c libsystem_pthread.dylib`_pthread_cond_wait + 984
�[40m�[37mdbug�[39m�[22m�[49m: frame #2: 0x000000010491ef6c libcoreclr.dylib`CorUnix::CPalSynchronizationManager::ThreadNativeWait(CorUnix::_ThreadNativeWaitData*, unsigned int, CorUnix::ThreadWakeupReason*, unsigned int*) + 320
�[40m�[37mdbug�[39m�[22m�[49m: frame #3: 0x000000010491ebec libcoreclr.dylib`CorUnix::CPalSynchronizationManager::BlockThread(CorUnix::CPalThread*, unsigned int, bool, bool, CorUnix::ThreadWakeupReason*, unsigned int*) + 380
�[40m�[37mdbug�[39m�[22m�[49m: frame #4: 0x00000001049230cc libcoreclr.dylib`CorUnix::InternalWaitForMultipleObjectsEx(CorUnix::CPalThread*, unsigned int, void* const*, int, unsigned int, int, int) + 1600
�[40m�[37mdbug�[39m�[22m�[49m: frame #5: 0x0000000104c15da8 libcoreclr.dylib`DebuggerRCThread::MainLoop() + 228
�[40m�[37mdbug�[39m�[22m�[49m: frame #6: 0x0000000104c15c70 libcoreclr.dylib`DebuggerRCThread::ThreadProc() + 256
�[40m�[37mdbug�[39m�[22m�[49m: frame #7: 0x0000000104c15a24 libcoreclr.dylib`DebuggerRCThread::ThreadProcStatic(void*) + 56
�[40m�[37mdbug�[39m�[22m�[49m: frame #8: 0x000000010492a0fc libcoreclr.dylib`CorUnix::CPalThread::ThreadEntry(void*) + 364
�[40m�[37mdbug�[39m�[22m�[49m: frame #9: 0x000000018c627bc8 libsystem_pthread.dylib`_pthread_start + 136
�[40m�[37mdbug�[39m�[22m�[49m: thread #7
�[40m�[37mdbug�[39m�[22m�[49m: frame #0: 0x000000018c5e93cc libsystem_kernel.dylib`__psynch_cvwait + 8
�[40m�[37mdbug�[39m�[22m�[49m: frame #1: 0x000000018c62809c libsystem_pthread.dylib`_pthread_cond_wait + 984
�[40m�[37mdbug�[39m�[22m�[49m: frame #2: 0x000000010491ef6c libcoreclr.dylib`CorUnix::CPalSynchronizationManager::ThreadNativeWait(CorUnix::_ThreadNativeWaitData*, unsigned int, CorUnix::ThreadWakeupReason*, unsigned int*) + 320
�[40m�[37mdbug�[39m�[22m�[49m: frame #3: 0x000000010491ebec libcoreclr.dylib`CorUnix::CPalSynchronizationManager::BlockThread(CorUnix::CPalThread*, unsigned int, bool, bool, CorUnix::ThreadWakeupReason*, unsigned int*) + 380
�[40m�[37mdbug�[39m�[22m�[49m: frame #4: 0x00000001049230cc libcoreclr.dylib`CorUnix::InternalWaitForMultipleObjectsEx(CorUnix::CPalThread*, unsigned int, void* const*, int, unsigned int, int, int) + 1600
�[40m�[37mdbug�[39m�[22m�[49m: frame #5: 0x0000000104a70078 libcoreclr.dylib`FinalizerThread::WaitForFinalizerEvent(CLREvent*) + 240
�[40m�[37mdbug�[39m�[22m�[49m: frame #6: 0x0000000104a701d8 libcoreclr.dylib`FinalizerThread::FinalizerThreadWorker(void*) + 264
�[40m�[37mdbug�[39m�[22m�[49m: frame #7: 0x0000000104a0dfa8 libcoreclr.dylib`ManagedThreadBase_DispatchOuter(ManagedThreadCallState*) + 248
�[40m�[37mdbug�[39m�[22m�[49m: frame #8: 0x0000000104a0e48c libcoreclr.dylib`ManagedThreadBase::FinalizerBase(void (*)(void*)) + 36
�[40m�[37mdbug�[39m�[22m�[49m: frame #9: 0x0000000104a70350 libcoreclr.dylib`FinalizerThread::FinalizerThreadStart(void*) + 88
�[40m�[37mdbug�[39m�[22m�[49m: frame #10: 0x000000010492a0fc libcoreclr.dylib`CorUnix::CPalThread::ThreadEntry(void*) + 364
�[40m�[37mdbug�[39m�[22m�[49m: frame #11: 0x000000018c627bc8 libsystem_pthread.dylib`_pthread_start + 136
�[40m�[37mdbug�[39m�[22m�[49m: thread #8, name = '.NET SigHandler'
�[40m�[37mdbug�[39m�[22m�[49m: frame #0: 0x000000018c5e67dc libsystem_kernel.dylib`read + 8
�[40m�[37mdbug�[39m�[22m�[49m: frame #1: 0x0000000102f6ce98 libSystem.Native.dylib`SignalHandlerLoop + 96
�[40m�[37mdbug�[39m�[22m�[49m: frame #2: 0x000000018c627bc8 libsystem_pthread.dylib`_pthread_start + 136
�[40m�[37mdbug�[39m�[22m�[49m: thread #9
�[40m�[37mdbug�[39m�[22m�[49m: frame #0: 0x000000018c5ebd04 libsystem_kernel.dylib`kevent + 8
�[40m�[37mdbug�[39m�[22m�[49m: frame #1: 0x0000000102f6b4a4 libSystem.Native.dylib`SystemNative_WaitForSocketEvents + 80
�[40m�[37mdbug�[39m�[22m�[49m: frame #2: 0x000000010665c9b4
�[40m�[37mdbug�[39m�[22m�[49m: frame #3: 0x000000010665c61c
�[40m�[37mdbug�[39m�[22m�[49m: frame #4: 0x000000010665c43c
�[40m�[37mdbug�[39m�[22m�[49m: frame #5: 0x0000000106541470
�[40m�[37mdbug�[39m�[22m�[49m: frame #6: 0x0000000106541218
�[40m�[37mdbug�[39m�[22m�[49m: frame #7: 0x0000000106541108
�[40m�[37mdbug�[39m�[22m�[49m: frame #8: 0x0000000104bbcc04 libcoreclr.dylib`CallDescrWorkerInternal + 132
�[40m�[37mdbug�[39m�[22m�[49m: frame #9: 0x0000000104a3a988 libcoreclr.dylib`DispatchCallSimple(unsigned long*, unsigned int, unsigned long long, unsigned int) + 268
�[40m�[37mdbug�[39m�[22m�[49m: frame #10: 0x0000000104a4cc6c libcoreclr.dylib`ThreadNative::KickOffThread_Worker(void*) + 148
�[40m�[37mdbug�[39m�[22m�[49m: frame #11: 0x0000000104a0dfa8 libcoreclr.dylib`ManagedThreadBase_DispatchOuter(ManagedThreadCallState*) + 248
�[40m�[37mdbug�[39m�[22m�[49m: frame #12: 0x0000000104a0e45c libcoreclr.dylib`ManagedThreadBase::KickOff(void (*)(void*), void*) + 32
�[40m�[37mdbug�[39m�[22m�[49m: frame #13: 0x0000000104a4cd44 libcoreclr.dylib`ThreadNative::KickOffThread(void*) + 172
�[40m�[37mdbug�[39m�[22m�[49m: frame #14: 0x000000010492a0fc libcoreclr.dylib`CorUnix::CPalThread::ThreadEntry(void*) + 364
�[40m�[37mdbug�[39m�[22m�[49m: frame #15: 0x000000018c627bc8 libsystem_pthread.dylib`_pthread_start + 136
�[40m�[37mdbug�[39m�[22m�[49m: thread #10
�[40m�[37mdbug�[39m�[22m�[49m: frame #0: 0x000000018c5e5c34 libsystem_kernel.dylib`mach_msg2_trap + 8
�[40m�[37mdbug�[39m�[22m�[49m: frame #1: 0x000000018c5f83a0 libsystem_kernel.dylib`mach_msg2_internal + 76
�[40m�[37mdbug�[39m�[22m�[49m: frame #2: 0x000000018c5ee764 libsystem_kernel.dylib`mach_msg_overwrite + 484
�[40m�[37mdbug�[39m�[22m�[49m: frame #3: 0x000000018c5e5fa8 libsystem_kernel.dylib`mach_msg + 24
�[40m�[37mdbug�[39m�[22m�[49m: frame #4: 0x000000018c712c0c CoreFoundation`__CFRunLoopServiceMachPort + 160
�[40m�[37mdbug�[39m�[22m�[49m: frame #5: 0x000000018c711528 CoreFoundation`__CFRunLoopRun + 1208
�[40m�[37mdbug�[39m�[22m�[49m: frame #6: 0x000000018c7109e8 CoreFoundation`CFRunLoopRunSpecific + 572
�[40m�[37mdbug�[39m�[22m�[49m: frame #7: 0x000000018dce0c78 Foundation`-[NSRunLoop(NSRunLoop) runMode:beforeDate:] + 212
�[40m�[37mdbug�[39m�[22m�[49m: frame #8: 0x0000000102eb2f28 mlaunch`xamarin_dyn_objc_msgSend + 160
�[40m�[37mdbug�[39m�[22m�[49m: frame #9: 0x00000001068a7d44
�[40m�[37mdbug�[39m�[22m�[49m: frame #10: 0x00000001068a7c08
�[40m�[37mdbug�[39m�[22m�[49m: frame #11: 0x00000001068a7a3c
�[40m�[37mdbug�[39m�[22m�[49m: frame #12: 0x00000001068a4a40
�[40m�[37mdbug�[39m�[22m�[49m: frame #13: 0x0000000106541418
�[40m�[37mdbug�[39m�[22m�[49m: frame #14: 0x0000000106541218
�[40m�[37mdbug�[39m�[22m�[49m: frame #15: 0x0000000106541108
�[40m�[37mdbug�[39m�[22m�[49m: frame #16: 0x0000000104bbcc04 libcoreclr.dylib`CallDescrWorkerInternal + 132
�[40m�[37mdbug�[39m�[22m�[49m: frame #17: 0x0000000104a3a988 libcoreclr.dylib`DispatchCallSimple(unsigned long*, unsigned int, unsigned long long, unsigned int) + 268
�[40m�[37mdbug�[39m�[22m�[49m: frame #18: 0x0000000104a4cc6c libcoreclr.dylib`ThreadNative::KickOffThread_Worker(void*) + 148
�[40m�[37mdbug�[39m�[22m�[49m: frame #19: 0x0000000104a0dfa8 libcoreclr.dylib`ManagedThreadBase_DispatchOuter(ManagedThreadCallState*) + 248
�[40m�[37mdbug�[39m�[22m�[49m: frame #20: 0x0000000104a0e45c libcoreclr.dylib`ManagedThreadBase::KickOff(void (*)(void*), void*) + 32
�[40m�[37mdbug�[39m�[22m�[49m: frame #21: 0x0000000104a4cd44 libcoreclr.dylib`ThreadNative::KickOffThread(void*) + 172
�[40m�[37mdbug�[39m�[22m�[49m: frame #22: 0x000000010492a0fc libcoreclr.dylib`CorUnix::CPalThread::ThreadEntry(void*) + 364
�[40m�[37mdbug�[39m�[22m�[49m: frame #23: 0x000000018c627bc8 libsystem_pthread.dylib`_pthread_start + 136
�[40m�[37mdbug�[39m�[22m�[49m: thread #11
�[40m�[37mdbug�[39m�[22m�[49m: frame #0: 0x000000018c5e78b0 libsystem_kernel.dylib`__workq_kernreturn + 8
�[40m�[37mdbug�[39m�[22m�[49m: thread #12
�[40m�[37mdbug�[39m�[22m�[49m: frame #0: 0x000000018c5e78b0 libsystem_kernel.dylib`__workq_kernreturn + 8
�[40m�[37mdbug�[39m�[22m�[49m: thread #13, name = 'com.apple.CFSocket.private'
�[40m�[37mdbug�[39m�[22m�[49m: frame #0: 0x000000018c5f0c2c libsystem_kernel.dylib`__select + 8
�[40m�[37mdbug�[39m�[22m�[49m: frame #1: 0x000000018c738a80 CoreFoundation`__CFSocketManager + 704
�[40m�[37mdbug�[39m�[22m�[49m: frame #2: 0x000000018c627bc8 libsystem_pthread.dylib`_pthread_start + 136
�[40m�[37mdbug�[39m�[22m�[49m: thread #14
�[40m�[37mdbug�[39m�[22m�[49m: frame #0: 0x000000018c5e78b0 libsystem_kernel.dylib`__workq_kernreturn + 8
�[40m�[37mdbug�[39m�[22m�[49m: (lldb) detach
�[40m�[37mdbug�[39m�[22m�[49m: Process 9276 detached
�[40m�[37mdbug�[39m�[22m�[49m: (lldb) quit
�[40m�[37mdbug�[39m�[22m�[49m: 9276 Execution timed out after 60 seconds and the process was killed.
�[40m�[37mdbug�[39m�[22m�[49m: Process mlaunch exited with 137
�[40m�[37mdbug�[39m�[22m�[49m: Failed to list crash reports from device.
�[40m�[37mdbug�[39m�[22m�[49m: Test run started but crashed and no test results were reported
�[40m�[37mdbug�[39m�[22m�[49m: No crash reports, waiting 30 seconds for the crash report service...
�[41m�[30mfail�[39m�[22m�[49m: Application test run crashed
Failed to launch the application, please try again. If the problem persists, try rebooting MacOS
�[40m�[32minfo�[39m�[22m�[49m: Uninstalling the application 'com.microsoft.maui.core.devicetests' from 'iPhone 11 Pro'
�[40m�[37mdbug�[39m�[22m�[49m:
�[40m�[37mdbug�[39m�[22m�[49m: Running /Applications/Xcode_26.1.1.app/Contents/Developer/usr/bin/simctl
�[40m�[37mdbug�[39m�[22m�[49m: An error was encountered processing the command (domain=com.apple.CoreSimulator.SimError, code=405):
�[40m�[37mdbug�[39m�[22m�[49m: Unable to lookup in current state: Shutdown
�[40m�[37mdbug�[39m�[22m�[49m: Process simctl exited with 149
�[41m�[30mfail�[39m�[22m�[49m: Failed to uninstall the app bundle! Check logs for more details!
XHarness exit code: 83 (APP_LAUNCH_FAILURE)
Passed: 0
Failed: 0
Tests completed with exit code: 83
🟢 With fix — 📱 ContentViewTests (RemoveContentMaskDoesNotThrowWhenDisposed): PASS ✅ · 204s
(truncated to last 15,000 chars)
de:beforeDate:] + 212
�[40m�[37mdbug�[39m�[22m�[49m: frame #8: 0x000000018dd543a4 Foundation`-[NSRunLoop(NSRunLoop) runUntilDate:] + 100
�[40m�[37mdbug�[39m�[22m�[49m: frame #9: 0x0000000100c2ef28 mlaunch`xamarin_dyn_objc_msgSend + 160
�[40m�[37mdbug�[39m�[22m�[49m: frame #10: 0x000000010418d83c
�[40m�[37mdbug�[39m�[22m�[49m: frame #11: 0x0000000104300e58
�[40m�[37mdbug�[39m�[22m�[49m: frame #12: 0x0000000104186abc
�[40m�[37mdbug�[39m�[22m�[49m: frame #13: 0x00000001041210b4
�[40m�[37mdbug�[39m�[22m�[49m: frame #14: 0x000000010393cd54
�[40m�[37mdbug�[39m�[22m�[49m: frame #15: 0x000000010283cc04 libcoreclr.dylib`CallDescrWorkerInternal + 132
�[40m�[37mdbug�[39m�[22m�[49m: frame #16: 0x00000001026bad30 libcoreclr.dylib`MethodDescCallSite::CallTargetWorker(unsigned long long const*, unsigned long long*, int) + 836
�[40m�[37mdbug�[39m�[22m�[49m: frame #17: 0x00000001025c1350 libcoreclr.dylib`RunMain(MethodDesc*, short, int*, PtrArray**) + 648
�[40m�[37mdbug�[39m�[22m�[49m: frame #18: 0x00000001025c1688 libcoreclr.dylib`Assembly::ExecuteMainMethod(PtrArray**, int) + 264
�[40m�[37mdbug�[39m�[22m�[49m: frame #19: 0x00000001025e929c libcoreclr.dylib`CorHost2::ExecuteAssembly(unsigned int, char16_t const*, int, char16_t const**, unsigned int*) + 640
�[40m�[37mdbug�[39m�[22m�[49m: frame #20: 0x00000001025af650 libcoreclr.dylib`coreclr_execute_assembly + 232
�[40m�[37mdbug�[39m�[22m�[49m: frame #21: 0x0000000100c2a140 mlaunch`mono_jit_exec + 204
�[40m�[37mdbug�[39m�[22m�[49m: frame #22: 0x0000000100c2decc mlaunch`xamarin_main + 884
�[40m�[37mdbug�[39m�[22m�[49m: frame #23: 0x0000000100c2f1f4 mlaunch`main + 64
�[40m�[37mdbug�[39m�[22m�[49m: frame #24: 0x000000018c286b98 dyld`start + 6076
�[40m�[37mdbug�[39m�[22m�[49m: thread #2
�[40m�[37mdbug�[39m�[22m�[49m: frame #0: 0x000000018c5e78b0 libsystem_kernel.dylib`__workq_kernreturn + 8
�[40m�[37mdbug�[39m�[22m�[49m: thread #3
�[40m�[37mdbug�[39m�[22m�[49m: frame #0: 0x000000018c5e5c34 libsystem_kernel.dylib`mach_msg2_trap + 8
�[40m�[37mdbug�[39m�[22m�[49m: frame #1: 0x000000018c5f83a0 libsystem_kernel.dylib`mach_msg2_internal + 76
�[40m�[37mdbug�[39m�[22m�[49m: frame #2: 0x000000018c5ee764 libsystem_kernel.dylib`mach_msg_overwrite + 484
�[40m�[37mdbug�[39m�[22m�[49m: frame #3: 0x000000018c5e5fa8 libsystem_kernel.dylib`mach_msg + 24
�[40m�[37mdbug�[39m�[22m�[49m: frame #4: 0x00000001025ad2f4 libcoreclr.dylib`MachMessage::Receive(unsigned int) + 80
�[40m�[37mdbug�[39m�[22m�[49m: frame #5: 0x00000001025ac61c libcoreclr.dylib`SEHExceptionThread(void*) + 164
�[40m�[37mdbug�[39m�[22m�[49m: frame #6: 0x000000018c627bc8 libsystem_pthread.dylib`_pthread_start + 136
�[40m�[37mdbug�[39m�[22m�[49m: thread #4, name = '.NET SynchManager'
�[40m�[37mdbug�[39m�[22m�[49m: frame #0: 0x000000018c5ebd04 libsystem_kernel.dylib`kevent + 8
�[40m�[37mdbug�[39m�[22m�[49m: frame #1: 0x00000001025a1304 libcoreclr.dylib`CorUnix::CPalSynchronizationManager::ReadBytesFromProcessPipe(int, unsigned char*, int) + 484
�[40m�[37mdbug�[39m�[22m�[49m: frame #2: 0x00000001025a09f0 libcoreclr.dylib`CorUnix::CPalSynchronizationManager::WorkerThread(void*) + 164
�[40m�[37mdbug�[39m�[22m�[49m: frame #3: 0x00000001025aa0fc libcoreclr.dylib`CorUnix::CPalThread::ThreadEntry(void*) + 364
�[40m�[37mdbug�[39m�[22m�[49m: frame #4: 0x000000018c627bc8 libsystem_pthread.dylib`_pthread_start + 136
�[40m�[37mdbug�[39m�[22m�[49m: thread #5
�[40m�[37mdbug�[39m�[22m�[49m: frame #0: 0x000000018c5e78b0 libsystem_kernel.dylib`__workq_kernreturn + 8
�[40m�[37mdbug�[39m�[22m�[49m: thread #6, name = '.NET EventPipe'
�[40m�[37mdbug�[39m�[22m�[49m: frame #0: 0x000000018c5ee498 libsystem_kernel.dylib`poll + 8
�[40m�[37mdbug�[39m�[22m�[49m: frame #1: 0x000000010289ce90 libcoreclr.dylib`ds_ipc_poll(_DiagnosticsIpcPollHandle*, unsigned long, unsigned int, void (*)(char const*, unsigned int)) + 172
�[40m�[37mdbug�[39m�[22m�[49m: frame #2: 0x000000010294abb0 libcoreclr.dylib`ds_ipc_stream_factory_get_next_available_stream(void (*)(char const*, unsigned int)) + 756
�[40m�[37mdbug�[39m�[22m�[49m: frame #3: 0x0000000102948a68 libcoreclr.dylib`server_thread(void*) + 372
�[40m�[37mdbug�[39m�[22m�[49m: frame #4: 0x00000001025aa0fc libcoreclr.dylib`CorUnix::CPalThread::ThreadEntry(void*) + 364
�[40m�[37mdbug�[39m�[22m�[49m: frame #5: 0x000000018c627bc8 libsystem_pthread.dylib`_pthread_start + 136
�[40m�[37mdbug�[39m�[22m�[49m: thread #7, name = '.NET DebugPipe'
�[40m�[37mdbug�[39m�[22m�[49m: frame #0: 0x000000018c5e6678 libsystem_kernel.dylib`__open + 8
�[40m�[37mdbug�[39m�[22m�[49m: frame #1: 0x000000018c5f16a4 libsystem_kernel.dylib`open + 64
�[40m�[37mdbug�[39m�[22m�[49m: frame #2: 0x000000010289da84 libcoreclr.dylib`TwoWayPipe::WaitForConnection() + 40
�[40m�[37mdbug�[39m�[22m�[49m: frame #3: 0x0000000102898578 libcoreclr.dylib`DbgTransportSession::TransportWorker() + 232
�[40m�[37mdbug�[39m�[22m�[49m: frame #4: 0x00000001028975c8 libcoreclr.dylib`DbgTransportSession::TransportWorkerStatic(void*) + 40
�[40m�[37mdbug�[39m�[22m�[49m: frame #5: 0x00000001025aa0fc libcoreclr.dylib`CorUnix::CPalThread::ThreadEntry(void*) + 364
�[40m�[37mdbug�[39m�[22m�[49m: frame #6: 0x000000018c627bc8 libsystem_pthread.dylib`_pthread_start + 136
�[40m�[37mdbug�[39m�[22m�[49m: thread #8, name = '.NET Debugger'
�[40m�[37mdbug�[39m�[22m�[49m: frame #0: 0x000000018c5e93cc libsystem_kernel.dylib`__psynch_cvwait + 8
�[40m�[37mdbug�[39m�[22m�[49m: frame #1: 0x000000018c62809c libsystem_pthread.dylib`_pthread_cond_wait + 984
�[40m�[37mdbug�[39m�[22m�[49m: frame #2: 0x000000010259ef6c libcoreclr.dylib`CorUnix::CPalSynchronizationManager::ThreadNativeWait(CorUnix::_ThreadNativeWaitData*, unsigned int, CorUnix::ThreadWakeupReason*, unsigned int*) + 320
�[40m�[37mdbug�[39m�[22m�[49m: frame #3: 0x000000010259ebec libcoreclr.dylib`CorUnix::CPalSynchronizationManager::BlockThread(CorUnix::CPalThread*, unsigned int, bool, bool, CorUnix::ThreadWakeupReason*, unsigned int*) + 380
�[40m�[37mdbug�[39m�[22m�[49m: frame #4: 0x00000001025a30cc libcoreclr.dylib`CorUnix::InternalWaitForMultipleObjectsEx(CorUnix::CPalThread*, unsigned int, void* const*, int, unsigned int, int, int) + 1600
�[40m�[37mdbug�[39m�[22m�[49m: frame #5: 0x0000000102895da8 libcoreclr.dylib`DebuggerRCThread::MainLoop() + 228
�[40m�[37mdbug�[39m�[22m�[49m: frame #6: 0x0000000102895c70 libcoreclr.dylib`DebuggerRCThread::ThreadProc() + 256
�[40m�[37mdbug�[39m�[22m�[49m: frame #7: 0x0000000102895a24 libcoreclr.dylib`DebuggerRCThread::ThreadProcStatic(void*) + 56
�[40m�[37mdbug�[39m�[22m�[49m: frame #8: 0x00000001025aa0fc libcoreclr.dylib`CorUnix::CPalThread::ThreadEntry(void*) + 364
�[40m�[37mdbug�[39m�[22m�[49m: frame #9: 0x000000018c627bc8 libsystem_pthread.dylib`_pthread_start + 136
�[40m�[37mdbug�[39m�[22m�[49m: thread #9
�[40m�[37mdbug�[39m�[22m�[49m: frame #0: 0x000000018c5e93cc libsystem_kernel.dylib`__psynch_cvwait + 8
�[40m�[37mdbug�[39m�[22m�[49m: frame #1: 0x000000018c62809c libsystem_pthread.dylib`_pthread_cond_wait + 984
�[40m�[37mdbug�[39m�[22m�[49m: frame #2: 0x000000010259ef6c libcoreclr.dylib`CorUnix::CPalSynchronizationManager::ThreadNativeWait(CorUnix::_ThreadNativeWaitData*, unsigned int, CorUnix::ThreadWakeupReason*, unsigned int*) + 320
�[40m�[37mdbug�[39m�[22m�[49m: frame #3: 0x000000010259ebec libcoreclr.dylib`CorUnix::CPalSynchronizationManager::BlockThread(CorUnix::CPalThread*, unsigned int, bool, bool, CorUnix::ThreadWakeupReason*, unsigned int*) + 380
�[40m�[37mdbug�[39m�[22m�[49m: frame #4: 0x00000001025a30cc libcoreclr.dylib`CorUnix::InternalWaitForMultipleObjectsEx(CorUnix::CPalThread*, unsigned int, void* const*, int, unsigned int, int, int) + 1600
�[40m�[37mdbug�[39m�[22m�[49m: frame #5: 0x00000001026f0078 libcoreclr.dylib`FinalizerThread::WaitForFinalizerEvent(CLREvent*) + 240
�[40m�[37mdbug�[39m�[22m�[49m: frame #6: 0x00000001026f01d8 libcoreclr.dylib`FinalizerThread::FinalizerThreadWorker(void*) + 264
�[40m�[37mdbug�[39m�[22m�[49m: frame #7: 0x000000010268dfa8 libcoreclr.dylib`ManagedThreadBase_DispatchOuter(ManagedThreadCallState*) + 248
�[40m�[37mdbug�[39m�[22m�[49m: frame #8: 0x000000010268e48c libcoreclr.dylib`ManagedThreadBase::FinalizerBase(void (*)(void*)) + 36
�[40m�[37mdbug�[39m�[22m�[49m: frame #9: 0x00000001026f0350 libcoreclr.dylib`FinalizerThread::FinalizerThreadStart(void*) + 88
�[40m�[37mdbug�[39m�[22m�[49m: frame #10: 0x00000001025aa0fc libcoreclr.dylib`CorUnix::CPalThread::ThreadEntry(void*) + 364
�[40m�[37mdbug�[39m�[22m�[49m: frame #11: 0x000000018c627bc8 libsystem_pthread.dylib`_pthread_start + 136
�[40m�[37mdbug�[39m�[22m�[49m: thread #10, name = '.NET SigHandler'
�[40m�[37mdbug�[39m�[22m�[49m: frame #0: 0x000000018c5e67dc libsystem_kernel.dylib`read + 8
�[40m�[37mdbug�[39m�[22m�[49m: frame #1: 0x0000000100ce8e98 libSystem.Native.dylib`SignalHandlerLoop + 96
�[40m�[37mdbug�[39m�[22m�[49m: frame #2: 0x000000018c627bc8 libsystem_pthread.dylib`_pthread_start + 136
�[40m�[37mdbug�[39m�[22m�[49m: thread #11
�[40m�[37mdbug�[39m�[22m�[49m: frame #0: 0x000000018c5ebd04 libsystem_kernel.dylib`kevent + 8
�[40m�[37mdbug�[39m�[22m�[49m: frame #1: 0x0000000100ce74a4 libSystem.Native.dylib`SystemNative_WaitForSocketEvents + 80
�[40m�[37mdbug�[39m�[22m�[49m: frame #2: 0x000000010429ca9c
�[40m�[37mdbug�[39m�[22m�[49m: frame #3: 0x000000010429c6f4
�[40m�[37mdbug�[39m�[22m�[49m: frame #4: 0x000000010429c43c
�[40m�[37mdbug�[39m�[22m�[49m: frame #5: 0x0000000104181568
�[40m�[37mdbug�[39m�[22m�[49m: frame #6: 0x0000000104181218
�[40m�[37mdbug�[39m�[22m�[49m: frame #7: 0x0000000104181140
�[40m�[37mdbug�[39m�[22m�[49m: frame #8: 0x000000010283cc04 libcoreclr.dylib`CallDescrWorkerInternal + 132
�[40m�[37mdbug�[39m�[22m�[49m: frame #9: 0x00000001026ba988 libcoreclr.dylib`DispatchCallSimple(unsigned long*, unsigned int, unsigned long long, unsigned int) + 268
�[40m�[37mdbug�[39m�[22m�[49m: frame #10: 0x00000001026ccc6c libcoreclr.dylib`ThreadNative::KickOffThread_Worker(void*) + 148
�[40m�[37mdbug�[39m�[22m�[49m: frame #11: 0x000000010268dfa8 libcoreclr.dylib`ManagedThreadBase_DispatchOuter(ManagedThreadCallState*) + 248
�[40m�[37mdbug�[39m�[22m�[49m: frame #12: 0x000000010268e45c libcoreclr.dylib`ManagedThreadBase::KickOff(void (*)(void*), void*) + 32
�[40m�[37mdbug�[39m�[22m�[49m: frame #13: 0x00000001026ccd44 libcoreclr.dylib`ThreadNative::KickOffThread(void*) + 172
�[40m�[37mdbug�[39m�[22m�[49m: frame #14: 0x00000001025aa0fc libcoreclr.dylib`CorUnix::CPalThread::ThreadEntry(void*) + 364
�[40m�[37mdbug�[39m�[22m�[49m: frame #15: 0x000000018c627bc8 libsystem_pthread.dylib`_pthread_start + 136
�[40m�[37mdbug�[39m�[22m�[49m: thread #12
�[40m�[37mdbug�[39m�[22m�[49m: frame #0: 0x000000018c5e5c34 libsystem_kernel.dylib`mach_msg2_trap + 8
�[40m�[37mdbug�[39m�[22m�[49m: frame #1: 0x000000018c5f83a0 libsystem_kernel.dylib`mach_msg2_internal + 76
�[40m�[37mdbug�[39m�[22m�[49m: frame #2: 0x000000018c5ee764 libsystem_kernel.dylib`mach_msg_overwrite + 484
�[40m�[37mdbug�[39m�[22m�[49m: frame #3: 0x000000018c5e5fa8 libsystem_kernel.dylib`mach_msg + 24
�[40m�[37mdbug�[39m�[22m�[49m: frame #4: 0x000000018c712c0c CoreFoundation`__CFRunLoopServiceMachPort + 160
�[40m�[37mdbug�[39m�[22m�[49m: frame #5: 0x000000018c711528 CoreFoundation`__CFRunLoopRun + 1208
�[40m�[37mdbug�[39m�[22m�[49m: frame #6: 0x000000018c7109e8 CoreFoundation`CFRunLoopRunSpecific + 572
�[40m�[37mdbug�[39m�[22m�[49m: frame #7: 0x000000018dce0c78 Foundation`-[NSRunLoop(NSRunLoop) runMode:beforeDate:] + 212
�[40m�[37mdbug�[39m�[22m�[49m: frame #8: 0x0000000100c2ef28 mlaunch`xamarin_dyn_objc_msgSend + 160
�[40m�[37mdbug�[39m�[22m�[49m: frame #9: 0x00000001042e9bd4
�[40m�[37mdbug�[39m�[22m�[49m: frame #10: 0x00000001042e9a98
�[40m�[37mdbug�[39m�[22m�[49m: frame #11: 0x00000001042e98cc
�[40m�[37mdbug�[39m�[22m�[49m: frame #12: 0x00000001042e64c8
�[40m�[37mdbug�[39m�[22m�[49m: frame #13: 0x0000000104181510
�[40m�[37mdbug�[39m�[22m�[49m: frame #14: 0x0000000104181218
�[40m�[37mdbug�[39m�[22m�[49m: frame #15: 0x0000000104181140
�[40m�[37mdbug�[39m�[22m�[49m: frame #16: 0x000000010283cc04 libcoreclr.dylib`CallDescrWorkerInternal + 132
�[40m�[37mdbug�[39m�[22m�[49m: frame #17: 0x00000001026ba988 libcoreclr.dylib`DispatchCallSimple(unsigned long*, unsigned int, unsigned long long, unsigned int) + 268
�[40m�[37mdbug�[39m�[22m�[49m: frame #18: 0x00000001026ccc6c libcoreclr.dylib`ThreadNative::KickOffThread_Worker(void*) + 148
�[40m�[37mdbug�[39m�[22m�[49m: frame #19: 0x000000010268dfa8 libcoreclr.dylib`ManagedThreadBase_DispatchOuter(ManagedThreadCallState*) + 248
�[40m�[37mdbug�[39m�[22m�[49m: frame #20: 0x000000010268e45c libcoreclr.dylib`ManagedThreadBase::KickOff(void (*)(void*), void*) + 32
�[40m�[37mdbug�[39m�[22m�[49m: frame #21: 0x00000001026ccd44 libcoreclr.dylib`ThreadNative::KickOffThread(void*) + 172
�[40m�[37mdbug�[39m�[22m�[49m: frame #22: 0x00000001025aa0fc libcoreclr.dylib`CorUnix::CPalThread::ThreadEntry(void*) + 364
�[40m�[37mdbug�[39m�[22m�[49m: frame #23: 0x000000018c627bc8 libsystem_pthread.dylib`_pthread_start + 136
�[40m�[37mdbug�[39m�[22m�[49m: thread #13
�[40m�[37mdbug�[39m�[22m�[49m: frame #0: 0x0000000000000000
�[40m�[37mdbug�[39m�[22m�[49m: thread #14, name = 'com.apple.CFSocket.private'
�[40m�[37mdbug�[39m�[22m�[49m: frame #0: 0x000000018c5f0c2c libsystem_kernel.dylib`__select + 8
�[40m�[37mdbug�[39m�[22m�[49m: frame #1: 0x000000018c738a80 CoreFoundation`__CFSocketManager + 704
�[40m�[37mdbug�[39m�[22m�[49m: frame #2: 0x000000018c627bc8 libsystem_pthread.dylib`_pthread_start + 136
�[40m�[37mdbug�[39m�[22m�[49m: (lldb) detach
�[40m�[37mdbug�[39m�[22m�[49m: (lldb) quit
�[40m�[37mdbug�[39m�[22m�[49m: Process 10652 detached
�[40m�[37mdbug�[39m�[22m�[49m: 10652 Execution timed out after 60 seconds and the process was killed.
�[40m�[37mdbug�[39m�[22m�[49m: Process mlaunch exited with 137
�[40m�[37mdbug�[39m�[22m�[49m: Failed to list crash reports from device.
�[40m�[37mdbug�[39m�[22m�[49m: Test run started but crashed and no test results were reported
�[40m�[37mdbug�[39m�[22m�[49m: No crash reports, waiting 30 seconds for the crash report service...
�[40m�[37mdbug�[39m�[22m�[49m: Found 1 new crash report(s)
�[40m�[37mdbug�[39m�[22m�[49m: - Adding /Users/cloudtest/Library/Logs/DiagnosticReports/Microsoft.Maui.Core.DeviceTests-2026-04-05-044407.ips
�[40m�[37mdbug�[39m�[22m�[49m: Successfully copied Microsoft.Maui.Core.DeviceTests-2026-04-05-044407.ips
�[41m�[30mfail�[39m�[22m�[49m: Application test run crashed
Failed to launch the application, please try again. If the problem persists, try rebooting MacOS
�[40m�[32minfo�[39m�[22m�[49m: Uninstalling the application 'com.microsoft.maui.core.devicetests' from 'iPhone 11 Pro'
�[40m�[37mdbug�[39m�[22m�[49m:
�[40m�[37mdbug�[39m�[22m�[49m: Running /Applications/Xcode_26.1.1.app/Contents/Developer/usr/bin/simctl
�[40m�[37mdbug�[39m�[22m�[49m: Process simctl exited with 0
�[40m�[32minfo�[39m�[22m�[49m: Application 'com.microsoft.maui.core.devicetests' was uninstalled successfully
XHarness exit code: 83 (APP_LAUNCH_FAILURE)
Passed: 57
Failed: 0
Tests completed with exit code: 83
⚠️ Issues found
- ❌ ContentViewTests (RemoveContentMaskDoesNotThrowWhenDisposed) PASSED without fix (should fail) — tests don't catch the bug
📁 Fix files reverted (2 files)
eng/pipelines/ci-copilot.ymlsrc/Core/src/Platform/iOS/ContentView.cs
🤖 AI Summary📊 Expand Full Review —
|
| # | Source | Approach | Test Result | Files Changed | Notes |
|---|---|---|---|---|---|
| PR | PR #34680 | Guard Handle != IntPtr.Zero before RemoveFromSuperLayer() |
❌ Gate FAILED (test passes with/without fix) | ContentView.cs + ContentViewTests.iOS.cs |
Fix logic correct; test design broken + nullable stub issues |
🔧 Fix — Analysis & Comparison
Fix Candidates
| # | Source | Approach | Test Result | Files Changed | Notes |
|---|---|---|---|---|---|
| PR | PR #34680 | Guard Handle != IntPtr.Zero before RemoveFromSuperLayer() |
❌ Gate FAILED (test passes with/without fix — wrong layer type) | ContentView.cs + ContentViewTests.iOS.cs |
Fix logic correct; test uses plain CAShapeLayer (no-op when disposed) instead of StaticCAShapeLayer |
| 1 | Attempt 1 (claude-opus-4.6) | Parent-side detachment: PlatformContent?.Layer.Mask = null + StaticCAShapeLayer in test + nullable fixes |
✅ PASS (2515/2515 tests) | ContentView.cs, ContentViewTests.iOS.cs |
Eliminates TOCTOU entirely; cleanest approach |
| 2 | Attempt 2 (claude-sonnet-4.6) | Keep Handle guard (PR's fix) + fix test to use StaticCAShapeLayer + nullable fixes |
✅ PASS (2515/2515 tests) | ContentView.cs, ContentViewTests.iOS.cs |
Minimal change to production code; test now properly validates fix |
| 3 | Attempt 3 (gpt-5.3-codex) | try/catch ObjectDisposedException + StaticCAShapeLayer in test + nullable fixes |
ContentView.cs, ContentViewTests.iOS.cs |
EAFP approach; handles TOCTOU window | |
| 4 | Attempt 4 (gpt-5.4) | Conditional identity check content?.Layer.Mask == _contentMask + StaticCAShapeLayer in test + nullable fixes |
ContentView.cs, ContentViewTests.iOS.cs |
Guards identity before clearing; redundant with Attempt 1 |
Cross-Pollination
| Model | Round | New Ideas? | Details |
|---|---|---|---|
| claude-opus-4.6 | 2 | No | NO NEW IDEAS — two passing candidates cover problem cleanly |
| claude-sonnet-4.6 | 2 | No | NO NEW IDEAS — handler-layer cleanup is more invasive refactor; no simpler alternative |
| gpt-5.3-codex | 2 (implied) | No | Round 1 idea (Dispose/MovedToWindow) is invasive; not pursued |
| gpt-5.4 | 2 (implied) | No | Round 1 idea (skip native detach in WillRemoveSubview) leaves stale mask on layer |
Exhausted: Yes — Round 2 returned NO NEW IDEAS from all models
Selected Fix: Attempt 1 (parent-side detachment PlatformContent?.Layer.Mask = null) — Reason: eliminates TOCTOU race entirely by never touching the potentially-disposed _contentMask. Simpler, more robust than Attempt 2's Handle guard. Validated with 2515/2515 tests passing.
Key discovery across attempts: The PR's test was broken because plain CAShapeLayer.RemoveFromSuperLayer() sends objc_msgSend(nil, sel) when disposed, which is a silent no-op in ObjC runtime. StaticCAShapeLayer overrides RemoveFromSuperLayer() and calls the managed base.RemoveFromSuperLayer() → GetNonNullHandle() → throws ObjectDisposedException. The test must use StaticCAShapeLayer to properly reproduce the crash.
📋 Report — Final Recommendation
⚠️ Final Recommendation: REQUEST CHANGES
Phase Status
| Phase | Status | Notes |
|---|---|---|
| Pre-Flight | ✅ COMPLETE | iOS/MacCatalyst crash in ContentView.RemoveContentMask(); 2 files changed |
| Gate | ❌ FAILED | Test RemoveContentMaskDoesNotThrowWhenDisposed passes with AND without fix |
| Try-Fix | ✅ COMPLETE | 4 attempts: 2 passing (Attempts 1 & 2), 2 infra-blocked (Attempts 3 & 4); Selected Fix: Attempt 1 |
| Report | ✅ COMPLETE |
Summary
PR #34680 fixes a real ObjectDisposedException crash in ContentView.RemoveContentMask() on iOS/MacCatalyst — the production fix is correct and was endorsed by @rolfbjarne. However, the gate failed because the new test does not properly reproduce the bug: it uses a plain CAShapeLayer instead of StaticCAShapeLayer, causing the test to pass regardless of whether the fix is present.
Two changes are required:
- Test must use
StaticCAShapeLayer(the actual production type) for the disposed layer injection BorderStrokeStubmust fix nullable properties (Paint? Stroke,float[]? StrokeDashPattern) to match theIStrokeinterface
Try-Fix exploration also found a cleaner alternative production fix (Attempt 1): replace _contentMask.RemoveFromSuperLayer() with PlatformContent?.Layer.Mask = null (parent-side detachment). This eliminates the TOCTOU race entirely.
Root Cause
During iOS view hierarchy teardown, WillRemoveSubview() fires RemoveContentMask() which calls _contentMask.RemoveFromSuperLayer(). _contentMask is a StaticCAShapeLayer — a subclass that overrides RemoveFromSuperLayer() and calls base.RemoveFromSuperLayer() via SuperHandle. When iOS has already started deallocating the native CAShapeLayer, GetNonNullHandle() throws ObjectDisposedException. This is the documented dotnet/macios#10562 pattern.
Why the gate test fails: The test injects a plain CAShapeLayer (not StaticCAShapeLayer) with a zeroed Handle. Plain CAShapeLayer.RemoveFromSuperLayer() calls objc_msgSend(nil, sel) which is a silent no-op in the ObjC runtime — it never throws even without the fix. StaticCAShapeLayer must be used because its override calls base.RemoveFromSuperLayer() → GetNonNullHandle() → throws when disposed.
Fix Quality
Production fix (Handle guard): Correct. Follows established pattern (ViewRenderer.cs, LayoutFactory2.cs, etc.). Endorsed by @rolfbjarne (dotnet/macios team). Has a minor TOCTOU window (Handle could zero between check and call) but this is negligible in practice for single-threaded UI code.
Alternative production fix (parent-side detachment — Attempt 1): Cleaner. Eliminates TOCTOU entirely by setting PlatformContent?.Layer.Mask = null instead of calling any method on the potentially-disposed _contentMask. Semantically equivalent — same effect (mask removed from layer graph), fewer risks. Validated: 2515/2515 tests pass.
Required Changes
Option A — Minimal (keep PR's Handle guard, just fix the test):
// ContentViewTests.iOS.cs — change plain CAShapeLayer to StaticCAShapeLayer
var disposedLayer = new StaticCAShapeLayer(); // was: new CAShapeLayer()
// Fix nullable stubs
public Paint? Stroke { get; set; } // was: public Paint Stroke { get; set; }
public float[]? StrokeDashPattern { get; set; } // was: public float[] StrokeDashPattern { get; set; }Option B — Preferred (parent-side detachment + test fix):
// ContentView.cs — replace RemoveContentMask() body
void RemoveContentMask()
{
var content = PlatformContent;
if (content is not null)
{
content.Layer.Mask = null;
}
_contentMask = null;
}
// ContentViewTests.iOS.cs — same test fixes as Option AOption B (Attempt 1) is recommended as the cleaner approach. Option A (Attempt 2) is acceptable and represents a minimal change if the author prefers to stay closer to the PR's original intent.
…ew.RemoveContentMask (#34744) Backport of #34680 to release/10.0.1xx-sr3 /cc @PureWeen @Oxymoron290 --------- Co-authored-by: Timothy Sturm <timothysturm6@gmail.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Timothy Sturm <timothysturm@microsoft.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
|
/azp run maui-pr-devicetests |
|
Azure Pipelines successfully started running 1 pipeline(s). |
|
/azp run maui-pr-devicetests |
|
Azure Pipelines successfully started running 1 pipeline(s). |
🔍 Prior Fix Regression CheckResult: ✅ No prior fix regressions detected Checked deleted lines across implementation files. No lines were identified as reversions of prior bug fixes.
|
|
/rebase |
Description
Fixes an
ObjectDisposedExceptioncrash inContentView.RemoveContentMask()on iOS/MacCatalyst when the underlyingCAShapeLayer(_contentMask) has already been deallocated by the native runtime during view hierarchy teardown.The Problem
During view lifecycle teardown,
WillRemoveSubview()callsRemoveContentMask(), which callsRemoveFromSuperLayer()on_contentMask. When iOS has already collected the nativeCAShapeLayer, the managed wrapper'sHandleisIntPtr.Zero, calling any method on it throwsObjectDisposedException.This is a manifestation of the long-standing iOS binding lifecycle issue documented in dotnet/macios#10562, where
deallocof a UIView callsRemoveFromSuperview()for every child while the native object is being deallocated, causing managed code to interact with already-disposed native objects.Crash stack:
The Fix
Added a disposal guard in
RemoveContentMask()checking_contentMask.Handle != IntPtr.Zerobefore callingRemoveFromSuperLayer(). This follows the established pattern used throughout the codebase inViewRenderer.cs,LayoutFactory2.cs,CellRenderer.cs,SkiaGraphicsView.cs, etc.Related Work
Testing
Added device test
RemoveContentMaskDoesNotThrowWhenDisposedthat:ContentViewwith an active clip maskCAShapeLayerHandle == IntPtr.ZeroRemoveFromSuperview()does not throw