Branch: refs/heads/main
  Home:   https://github.com/WebKit/WebKit
  Commit: 42ca5cc802a1492a3d701874b0e7cbd03aa2f948
      
https://github.com/WebKit/WebKit/commit/42ca5cc802a1492a3d701874b0e7cbd03aa2f948
  Author: Chris Dumez <[email protected]>
  Date:   2026-09-10 (Thu, 10 Sep 2026)

  Changed paths:
    M Source/WebCore/platform/mock/MockRealtimeVideoSource.cpp
    M Source/WebCore/platform/mock/MockRealtimeVideoSource.h

  Log Message:
  -----------
  MockRealtimeVideoSource shares five members between its capture run loop and 
its caller's thread without synchronization
https://bugs.webkit.org/show_bug.cgi?id=323742

Reviewed by Jean-Yves Avenard.

Frames are generated on m_runLoop, a dedicated run loop, while the source is 
controlled from
the caller's thread; generateFrame() and generatePhoto() assert !isMainThread() 
to say so. The
class already guards m_imageBuffer and m_drawingState with a lock, makes 
m_isTakingPhoto and
m_captureWasInterrupted atomic, and marshals timer start and stop onto 
m_runLoop. Five members
were left out of all of that, and the run loop reaches four of them indirectly, 
through helper
calls, which is what kept them hidden:

- m_startTime and m_elapsedTime are written by startProducingData() and 
stopProducingData(),
  and read by elapsedTime(), which drawText() and 
MockRealtimeVideoSourceMac::updateSampleBuffer()
  both call while generating a frame.
- m_preset is written by applyFrameRateAndZoomWithPreset() and read by 
captureSize(), which the
  whole draw path calls.
- m_deviceOrientation is written by orientationChanged() and
  rotationAngleForHorizonLevelDisplayChanged(), and read by 
videoFrameRotation() from
  updateSampleBuffer().
- m_delayUntil is written by delaySamples() and both read and cleared by 
generateFrame().

Each is fixed by whichever mechanism matches how it is reached rather than by 
one blanket
approach. m_startTime, m_elapsedTime and m_preset become WTF_GUARDED_BY_LOCK: 
every reader on
the run loop already held the lock, so only the writers needed changing, and 
elapsedTime() and
captureSize() get assertIsHeld() to match how the surrounding code already 
declares this.
m_deviceOrientation becomes atomic instead, because the lock does not fit it: 
videoFrameRotation()
is virtual on RealtimeMediaSource and so may be called from anywhere, and 
settings() reads the
member on the caller's thread. m_delayUntil moves entirely onto m_runLoop by 
dispatching from
delaySamples(), the same way startCaptureTimer() and stopCaptureTimer() already 
work; the
deadline is still computed at call time so it does not shift with dispatch 
latency.

Annotating m_preset immediately turned up a third accessor that reading the 
code had not:
settings() reads it on the caller's thread, which now takes the lock for that 
one read.
applyFrameRateAndZoomWithPreset() is restructured so setIntrinsicSize(), which 
notifies
observers, is not called while holding the lock.

The lock is renamed from m_imageBufferLock to m_frameGenerationLock. It already 
guarded
m_drawingState and now covers three further members that are not image buffers.

None of this is reachable by web content: MockRealtimeVideoSource is only 
created by
MockRealtimeMediaSourceCenter, that is, when mock capture devices are enabled 
for testing. Nor
was any of it a memory-safety problem, since everything read across the thread 
boundary is
plain data, a MonotonicTime, a Seconds, an enum, or the IntSize inside 
m_preset. The visible
symptom would have been a wrong timestamp, rotation or frame size in a 
generated mock frame.

* Source/WebCore/platform/mock/MockRealtimeVideoSource.cpp:
(WebCore::MockRealtimeVideoSource::takePhotoInternal):
(WebCore::MockRealtimeVideoSource::settings):
(WebCore::MockRealtimeVideoSource::applyFrameRateAndZoomWithPreset):
(WebCore::MockRealtimeVideoSource::captureSize const):
(WebCore::MockRealtimeVideoSource::invalidateDrawingState):
(WebCore::MockRealtimeVideoSource::drawingState):
(WebCore::MockRealtimeVideoSource::settingsDidChange):
(WebCore::MockRealtimeVideoSource::startProducingData):
(WebCore::MockRealtimeVideoSource::stopProducingData):
(WebCore::MockRealtimeVideoSource::elapsedTime):
(WebCore::MockRealtimeVideoSource::drawText):
(WebCore::MockRealtimeVideoSource::delaySamples):
(WebCore::MockRealtimeVideoSource::generatePhoto):
(WebCore::MockRealtimeVideoSource::generateFrameInternal):
(WebCore::MockRealtimeVideoSource::generateFrame):
(WebCore::MockRealtimeVideoSource::imageBuffer):
(WebCore::MockRealtimeVideoSource::imageBufferInternal):
(WebCore::MockRealtimeVideoSource::orientationChanged):
* Source/WebCore/platform/mock/MockRealtimeVideoSource.h:
(WebCore::MockRealtimeVideoSource::WTF_GUARDED_BY_LOCK):

Canonical link: https://commits.webkit.org/320813@main



To unsubscribe from these emails, change your notification settings at 
https://github.com/WebKit/WebKit/settings/notifications

Reply via email to