Skip to content

Close the stop and pause results the recorder gets from MediaCapture - #3431

Merged
FrayxRulez merged 1 commit into
developfrom
close-record-results
Sep 16, 2026
Merged

FrayxRulez merged 1 commit into
developfrom
close-record-results

Conversation

@FrayxRulez

Copy link
Copy Markdown
Collaborator

Reported by crash telemetry on 12.10.5.0 (X64), on the finalizer thread.

NativeException
ACCESS_VIOLATION Reading address 0x00007ffa620a4f90

   7  VariantClear+0x17b
   8  PropVariantClearWorker+0x16a            onecore\com\combase\util\propvar.cxx:244
   9  CMFSample::DeleteAllItems+0x6e
  10  CPooledSample::_FinalRelease+0x33
  11  CMFSample::Release+0x3a
  13  MediaFramePropertySetImpl::~MediaFramePropertySetImpl+0x78
  16  MediaFrameImpl::~MediaFrameImpl+0x4f
  17  VideoFrameImpl::`vector deleting destructor'+0x14
  20  RecordResultServer::~RecordResultServer+0x52
                                              avcore\mf\winrt\mediacapture\recordresult.cpp:32
  21  MediaCaptureStopResultServer::`scalar deleting destructor'+0x14
  23  CAgileReferenceToAgileObject::`scalar deleting destructor'+0x34
  26  Windows::Internal::AsyncOperation<IAsyncOperation<MediaCaptureStopResult*>, ...,
      CMarshaledInterfaceResult<IMediaCaptureStopResult>, ...>::~AsyncOperation+0x102
                                              onecore\internal\sdk\inc\winrt\asyncoperation.h:563
  29  WinRT.IObjectReference.Release()        WinRT.Runtime\ObjectReference.cs:413
  30  WinRT.IObjectReference.Dispose()        WinRT.Runtime\ObjectReference.cs:387
  31  WinRT.IObjectReference.Finalize()       WinRT.Runtime\ObjectReference.cs:151
  32  System.Runtime.__Finalizer.DrainQueue()
  34  FinalizerStart+0x8e

Cause

OpusRecorder.StopAsync stops the recording with LowLagMediaRecording.StopWithResultAsync,
reads RecordDuration off the MediaCaptureStopResult and drops it, then disposes
MediaCapture in the same finally. The result is never closed, so it stays alive until the
GC gets to it, and with it the VideoFrame it owns — a wrapper over a sample from the capture
pipeline's pool.

When the finalizer eventually releases the async operation that still held the result, the
whole chain is destroyed: the result, the video frame, its property set, and finally the
Media Foundation sample. Clearing the sample's attributes calls Release through a vtable
that belonged to the capture pipeline — long since torn down — and the read faults. The fault
address is in the image range, not the heap: the object's memory was still readable, its
vtable's module was not.

The report's log agrees with the stack. A video message was recorded and discarded, and the
crash landed 160 seconds later with nothing in between but a periodic timer — a delay only the
GC explains. MediaCapturePauseResult is the same object with the same owner and the same
last frame, so it has the same problem.

Fix

Read the duration, close the last frame and close the result, while the device is still open.
Both result types are IClosable precisely so this doesn't have to wait for a finalizer; the
last frame is the only thing either of them owns, and nothing here ever wanted it.

StopAsync and PauseAsync now hand back a TimeSpan? rather than the projection, so there
is no result left for a caller to leak.

Not built: no UWP/.NET Native build environment here. The file parses clean under Roslyn,
which catches typos and nothing more.

@FrayxRulez
FrayxRulez merged commit 6762611 into develop Sep 16, 2026
1 check passed
@FrayxRulez
FrayxRulez deleted the close-record-results branch September 16, 2026 08:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant