Skip to content

Conversation

tomasz-karczewski-red
Copy link

@tomasz-karczewski-red tomasz-karczewski-red commented Jun 12, 2025

This fixes race condition happening during LayerTreeHost construction The problem is seen with Process Swap On Cross-Site Navigation enabled.

The race condition happens during LayerTreeHost construction. The scenario is:

  • on THREAD_A (main thread) LayerTreeHost constructor starts; it first creates AcceleratedSurfaceLibWPE, then ThreadedCompositor

  • ThreadedCompositor constructor creates run loop (m_compositingRunLoop), executes & synchronously waits for initialization task on the run loop. This task calls m_client.nativeSurfaceHandleForCompositing() on THREAD_B (compositing thread) and this ends up calling AcceleratedSurfaceLibWPE::initialize() Note: at this point, LayerTreeHost constructor hasn't set LayerTreeHost::m_compositor value yet

  • still on THREAD_B, AcceleratedSurfaceLibWPE::initialize connects backend events (wpe_renderer_backend_egl_target_set_client). And sometimes we get first frame_complete event quickly (I've only seen that with PSON enabled). The handler for frame_complete is already registered, and it calls surface.m_client.frameComplete(). And LayerTreeHost::frameComplete() calls 'm_compositor->frameComplete()', but this requires THREAD_A to already have set m_compositor value in ThreadedCompositor constructor, and some memory barrier between threads A & B. So m_compositor can be null here, which causes SIGSEGV.

The proposed fix introduces additional 'LayerTreeHost::initialized' atomic bool which enables to prevent this case and adds memory barrier (via atomic_bool load/store) between threads.

ca3045d

Build-Tests Layout-Tests
✅ 🛠 wpe-238-amd64-build ✅ 🧪 wpe-238-amd64-layout
✅ 🛠 wpe-238-arm32-build ✅ 🧪 wpe-238-arm32-layout

This fixes race condition happening during LayerTreeHost construction
The problem is seen with Process Swap On Cross-Site Navigation enabled.

The race condition happens during LayerTreeHost construction. The scenario is:

- on THREAD_A (main thread) LayerTreeHost constructor starts; it first
  creates AcceleratedSurfaceLibWPE, then ThreadedCompositor

- ThreadedCompositor constructor creates run loop (m_compositingRunLoop),
  executes & synchronously waits for initialization task on the run loop.
  This task calls m_client.nativeSurfaceHandleForCompositing() on THREAD_B (compositing thread)
  and this ends up calling AcceleratedSurfaceLibWPE::initialize()
  Note: at this point, LayerTreeHost constructor hasn't set
  LayerTreeHost::m_compositor value yet

- still on THREAD_B, AcceleratedSurfaceLibWPE::initialize connects backend
  events (wpe_renderer_backend_egl_target_set_client). And sometimes we get
  first frame_complete event quickly (I've only seen that with PSON enabled).
  The handler for frame_complete is already registered, and it calls surface.m_client.frameComplete().
  And LayerTreeHost::frameComplete() calls 'm_compositor->frameComplete()', but this
  requires THREAD_A to already have set m_compositor value in ThreadedCompositor
  constructor, and some memory barrier between threads A & B.
  So m_compositor can be null here, which causes SIGSEGV.

The proposed fix introduces additional 'LayerTreeHost::initialized' atomic bool
which enables to prevent this case and adds memory barrier (via atomic_bool load/store)
between threads.
@tomasz-karczewski-red
Copy link
Author

associated RDK ticket: https://jira.rdkcentral.com/jira/browse/RDKDEV-1128

@modeveci
Copy link

modeveci commented Oct 3, 2025

@emutavchi , Is this also ok for you to integrate? Could you please look at this PR?

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

Labels

Development

Successfully merging this pull request may close these issues.

2 participants