[all-commits] [llvm/llvm-project] 348061: [lldb] Fix deadlock when scripted frame providers ...

Med Ismail Bennani via All-commits all-commits at lists.llvm.org
Tue Apr 14 17:34:20 PDT 2026


  Branch: refs/heads/main
  Home:   https://github.com/llvm/llvm-project
  Commit: 348061d58dfe5e59027a0d6d51f916197cdd8d68
      https://github.com/llvm/llvm-project/commit/348061d58dfe5e59027a0d6d51f916197cdd8d68
  Author: Med Ismail Bennani <ismail at bennani.ma>
  Date:   2026-04-14 (Tue, 14 Apr 2026)

  Changed paths:
    M lldb/include/lldb/Target/Process.h
    M lldb/source/Target/Process.cpp
    M lldb/source/Target/Thread.cpp
    A lldb/test/API/functionalities/scripted_frame_provider/was_hit_deadlock/Makefile
    A lldb/test/API/functionalities/scripted_frame_provider/was_hit_deadlock/TestWasHitWithFrameProviderDeadlock.py
    A lldb/test/API/functionalities/scripted_frame_provider/was_hit_deadlock/bkpt_resolver.py
    A lldb/test/API/functionalities/scripted_frame_provider/was_hit_deadlock/frame_provider.py
    A lldb/test/API/functionalities/scripted_frame_provider/was_hit_deadlock/main.c

  Log Message:
  -----------
  [lldb] Fix deadlock when scripted frame providers load on private state thread (#191913)

Frame providers are an overlay on top of the parent reality (the
unwinder stack). The private state thread (PST) manages the stop of that
parent reality, so the correct view for PST logic IS the parent --
providers should only be applied once the process has settled and
clients query the stopped state.

When a scripted breakpoint's `was_hit` callback calls
`EvaluateExpression` on the PST, `RunThreadPlan` spawns an override PST
(Thread B) and reassigns `m_current_private_state_thread_sp` to it. Two
threads then need to see parent frames:

- Thread B (override PST): processes stop events via
`HandlePrivateEvent` -> `ShouldStop` -> `GetStackFrameList`. If it loads
a provider, the provider's Python code can acquire locks held by Thread
A, causing a deadlock.

- Thread A (original PST): processes events inline via
`FindNextEventInternal` -> `DoOnRemoval` -> `GetStackFrameList`. After
the override is created, `CurrentThreadIsPrivateStateThread` no longer
recognizes Thread A (it checks against
`m_current_private_state_thread_sp`, which now points to Thread B).

The existing re-entrancy guard in `GetStackFrameList` (e1cd558) only
triggers when a provider is already active. In the deadlock scenario,
provider loading is being initiated for the first time, so the guard
does not trigger.

This patch introduces `PrivateStateThreadGuard`, an RAII guard that sets
a `thread_local` flag checked by `GetStackFrameList` to return parent
frames instead of loading providers. The guard is activated in two
places:

- `RunPrivateStateThread`: for override PSTs only (identified via a new
`is_override` flag on `PrivateStateThread`). The original PST does not
set the guard here, so normal stepping still sees provider-augmented
frames.

- `RunThreadPlan`: for the original PST, scoped to the event processing
window when an override has been spawned.

rdar://174679105

Signed-off-by: Med Ismail Bennani <ismail at bennani.ma>



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


More information about the All-commits mailing list