[Lldb-commits] [lldb] [LLDB] Support enabling/disabling InstrumentationRuntime plugins during a debug session (PR #190083)
Dan Liew via lldb-commits
lldb-commits at lists.llvm.org
Tue Apr 7 13:52:14 PDT 2026
================
@@ -2464,7 +2489,36 @@ PluginManager::GetInstrumentationRuntimePluginInfo() {
}
bool PluginManager::SetInstrumentationRuntimePluginEnabled(llvm::StringRef name,
bool enable) {
- return GetInstrumentationRuntimeInstances().SetInstanceEnabled(name, enable);
+ if (!GetInstrumentationRuntimeInstances().SetInstanceEnabled(name, enable))
+ return false;
+
+ // Find the `InstrumentationRuntimeType` from the plugin name
+ auto type_cb = GetInstrumentationRuntimeInstances().GetTypeCallbackForName(
+ name, /*enabled_only=*/false);
+ if (!type_cb)
+ return false;
+ auto instrumentation_ty = type_cb();
+
+ // Notify all alive processes to enable/disable the plugin
+ bool success = true;
+ for (size_t di = 0; di < Debugger::GetNumDebuggers(); ++di) {
+ DebuggerSP debugger_sp = Debugger::GetDebuggerAtIndex(di);
+ if (!debugger_sp)
----------------
delcypher wrote:
I tried doing this and I ran into a deadlock. It seems while we activate a plugin this eventually calls `lldb_private::Debugger::ReportProgress` which tries to hold the same mutex that we are holding in `Debugger::ForEachDebugger`. This causes deadlock.
If we wanted to fix this properly I think Debugger needs to use `std::recursive_mutex` to avoid the deadlock. A hacky alternative would be hold the DebuggerList lock long enough to make a copy of it and then iterate on the copy without holding on to the lock. It's not really proper locking as it only protects us from the list being changed underneath us by another thread but it doesn't protect us from a debugger from being created/destroy while we in the middle of activating plugins.
Let me know what you'd like to do.
```
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGSTOP
frame #0: 0x0000000182dbd9c8 libsystem_kernel.dylib`__psynch_mutexwait + 8
frame #1: 0x0000000182dfae3c libsystem_pthread.dylib`_pthread_mutex_firstfit_lock_wait + 84
frame #2: 0x0000000182df8868 libsystem_pthread.dylib`_pthread_mutex_firstfit_lock_slow + 220
frame #3: 0x0000000182d2f888 libc++.1.dylib`std::__1::mutex::lock() + 16
frame #4: 0x0000000124f365e4 LLDB`std::__1::lock_guard<std::__1::mutex>::lock_guard[abi:sqn210106](this=0x000000016d1ced98, __m=0x00000001321bb0d0) at lock_guard.h:32:10
frame #5: 0x0000000124f364a0 LLDB`std::__1::lock_guard<std::__1::mutex>::lock_guard[abi:sqn210106](this=0x000000016d1ced98, __m=0x00000001321bb0d0) at lock_guard.h:31:19
* frame #6: 0x000000012a30dd40 LLDB`lldb_private::Debugger::ReportProgress(progress_id=240, title="Looking up functions", details="", completed=0, total=17, debugger_id= Has Value=false , progress_broadcast_bit=1) at Debugger.cpp:1755:31
frame #7: 0x000000012a439d64 LLDB`lldb_private::Progress::ReportProgress(this=0x000000016d1cf150) at Progress.cpp:108:3
frame #8: 0x000000012a439b9c LLDB`lldb_private::Progress::Progress(this=0x000000016d1cf150, title="Looking up functions", details="", total= Has Value=true , debugger=0x0000000000000000, minimum_report_time=Timeout<std::__1::ratio<1L, 1000000000L> > @ 0x000000016d1cef88, origin=eInternal) at Progress.cpp:45:3
frame #9: 0x000000012a439e30 LLDB`lldb_private::Progress::Progress(this=0x000000016d1cf150, title="Looking up functions", details="", total= Has Value=true , debugger=0x0000000000000000, minimum_report_time=Timeout<std::__1::ratio<1L, 1000000000L> > @ 0x000000016d1cf000, origin=eInternal) at Progress.cpp:43:37
frame #10: 0x00000001270ec1b0 LLDB`lldb_private::plugin::dwarf::SymbolFileDWARFDebugMap::ForEachSymbolFile(this=0x0000000c6f881980, description="", closure=function<lldb_private::IterationAction (lldb_private::plugin::dwarf::SymbolFileDWARF &)> @ 0x000000016d1cf2f8) at SymbolFileDWARFDebugMap.cpp:736:12
frame #11: 0x00000001270ed84c LLDB`lldb_private::plugin::dwarf::SymbolFileDWARFDebugMap::FindFunctions(this=0x0000000c6f881980, lookup_info=0x0000000c71507480, parent_decl_ctx=0x000000016d1cf678, include_inlines=true, sc_list=0x000000016d1cf6f0) at SymbolFileDWARFDebugMap.cpp:1113:3
frame #12: 0x000000012a3b45cc LLDB`lldb_private::Module::FindFunctions(this=0x0000000c6e5de318, lookup_infos=size=1, parent_decl_ctx=0x000000016d1cf678, options=0x000000016d1cf6c4, sc_list=0x000000016d1cf6f0) at Module.cpp:825:14
frame #13: 0x000000012a2dd184 LLDB`lldb_private::BreakpointResolverName::SearchCallback(this=0x0000000c6ecce000, filter=0x0000000c6ec06558, context=0x000000016d1cf828, addr=0x0000000000000000) at BreakpointResolverName.cpp:274:28
frame #14: 0x000000012a43ee98 LLDB`lldb_private::SearchFilter::DoModuleIteration(this=0x0000000c6ec06558, context=0x000000016d1cf9f8, searcher=0x0000000c6ecce000) at SearchFilter.cpp:275:20
frame #15: 0x000000012a43ec8c LLDB`lldb_private::SearchFilter::Search(this=0x0000000c6ec06558, searcher=0x0000000c6ecce000) at SearchFilter.cpp:220:3
frame #16: 0x000000012a2ca4e4 LLDB`lldb_private::BreakpointResolver::ResolveBreakpoint(this=0x0000000c6ecce000, filter=0x0000000c6ec06558) at BreakpointResolver.cpp:183:10
frame #17: 0x000000012a2a5c3c LLDB`lldb_private::Breakpoint::ResolveBreakpoint(this=0x0000000c6dc5db80) at Breakpoint.cpp:512:20
frame #18: 0x000000012a7372d4 LLDB`lldb_private::Target::AddBreakpoint(this=0x0000000c6ef3a800, bp_sp=std::__1::shared_ptr<lldb_private::Breakpoint>::element_type @ 0x0000000c6dc5db80 strong=3 weak=2, internal=true) at Target.cpp:822:10
frame #19: 0x000000012a7397cc LLDB`lldb_private::Target::CreateBreakpoint(this=0x0000000c6ef3a800, filter_sp=std::__1::shared_ptr<lldb_private::SearchFilter>::element_type @ 0x0000000c6ec06558 strong=4 weak=0, resolver_sp=std::__1::shared_ptr<lldb_private::BreakpointResolver>::element_type @ 0x0000000c6ecce000 strong=2 weak=0, internal=true, request_hardware=false, resolve_indirect_symbols=true) at Target.cpp:801:5
frame #20: 0x000000012a739324 LLDB`lldb_private::Target::CreateBreakpoint(this=0x0000000c6ef3a800, containingModules=0x0000000000000000, containingSourceFiles=0x0000000000000000, func_names=size=2, func_name_type_mask=eFunctionNameTypeFull, language=eLanguageTypeUnknown, offset=0, skip_prologue=eLazyBoolNo, internal=true, hardware=false) at Target.cpp:636:13
frame #21: 0x000000012533216c LLDB`lldb_private::InstrumentationRuntimeBoundsSafety::Activate(this=0x0000000c6f37a170) at InstrumentationRuntimeBoundsSafety.cpp:454:53
frame #22: 0x000000012a661214 LLDB`lldb_private::InstrumentationRuntime::ModulesDidLoad(lldb_private::ModuleList&)::$_0::operator()(this=0x000000016d1d0140, module_sp=std::__1::shared_ptr<lldb_private::Module>::element_type @ 0x0000000c6e924018 strong=10 weak=36) const at InstrumentationRuntime.cpp:51:9
frame #28: 0x000000012a3c9dfc LLDB`std::__1::function<lldb_private::IterationAction (std::__1::shared_ptr<lldb_private::Module> const&)>::operator()(this= Lambda in File InstrumentationRuntime.cpp at Line 40, __arg=std::__1::shared_ptr<lldb_private::Module>::element_type @ 0x0000000c6e924018 strong=10 weak=36) const at function.h:772:10
frame #29: 0x000000012a3c76c0 LLDB`lldb_private::ModuleList::ForEach(this=0x000000016d1d0238, callback= Lambda in File InstrumentationRuntime.cpp at Line 40) const at ModuleList.cpp:1375:9
frame #30: 0x000000012a65f674 LLDB`lldb_private::InstrumentationRuntime::ModulesDidLoad(this=0x0000000c6f37a170, module_list=0x000000016d1d0238) at InstrumentationRuntime.cpp:40:15
frame #31: 0x000000012a65f824 LLDB`lldb_private::InstrumentationRuntime::Enable(this=0x0000000c6f37a170) at InstrumentationRuntime.cpp:86:5
frame #32: 0x000000012a6aeb50 LLDB`lldb_private::Process::SetInstrumentationRuntimeEnabled(this=0x0000000c6f18b000, irt=eInstrumentationRuntimeTypeBoundsSafety, enabled=true) at Process.cpp:6307:22
frame #33: 0x000000012a436f50 LLDB`lldb_private::PluginManager::SetInstrumentationRuntimePluginEnabled(llvm::StringRef, bool)::$_0::operator()(this=0x0000000c71db5128, debugger_sp=std::__1::shared_ptr<lldb_private::Debugger>::element_type @ 0x0000000103e55420 strong=3 weak=3) const at PluginManager.cpp:2510:47
frame #39: 0x000000012a30d180 LLDB`std::__1::function<void (std::__1::shared_ptr<lldb_private::Debugger>)>::operator()(this=0x000000016d1d0688, __arg=nullptr) const at function.h:772:10
frame #40: 0x000000012a30d128 LLDB`lldb_private::Debugger::ForEachDebugger(callback=function<void (std::__1::shared_ptr<lldb_private::Debugger>)> @ 0x000000016d1d0688) at Debugger.cpp:1612:7
frame #41: 0x000000012a3d5158 LLDB`lldb_private::PluginManager::SetInstrumentationRuntimePluginEnabled(name="BoundsSafety", enable=true) at PluginManager.cpp:2505:3
frame #47: 0x000000012a8f8968 LLDB`std::__1::function<bool (llvm::StringRef, bool)>::operator()(this= Function = lldb_private::PluginManager::SetInstrumentationRuntimePluginEnabled(llvm::StringRef, bool) , __arg="BoundsSafety", __arg=true) const at function.h:772:10
frame #48: 0x000000012a8f8844 LLDB`(anonymous namespace)::SetEnableOnMatchingPlugins(llvm::StringRef const&, lldb_private::CommandReturnObject&, bool)::$_0::operator()(this=0x000000016d1d0b40, plugin_namespace=0x0000000132256078, plugins=size=1) const at CommandObjectPlugin.cpp:92:16
frame #54: 0x000000012a8f66bc LLDB`std::__1::function<void (lldb_private::PluginNamespace const&, std::__1::vector<lldb_private::RegisteredPluginInfo, std::__1::allocator<lldb_private::RegisteredPluginInfo>> const&)>::operator()(this=0x000000016d1d0b38, __arg=0x0000000132256078, __arg=size=1) const at function.h:772:10
frame #55: 0x000000012a8f6534 LLDB`(anonymous namespace)::ActOnMatchingPlugins(pattern="instrumentation-runtime.BoundsSafety", action=function<void (const lldb_private::PluginNamespace &, const std::__1::vector<lldb_private::RegisteredPluginInfo, std::__1::allocator<lldb_private::RegisteredPluginInfo> > &)> @ 0x000000016d1d0b38) at CommandObjectPlugin.cpp:75:7
frame #56: 0x000000012a8f8310 LLDB`(anonymous namespace)::SetEnableOnMatchingPlugins(pattern="instrumentation-runtime.BoundsSafety", result=0x000000016d1d1810, enabled=true) at CommandObjectPlugin.cpp:87:10
frame #57: 0x000000012a8f8238 LLDB`DoPluginEnableDisable(command=0x000000016d1d0db0, result=0x000000016d1d1810, enable=true) at CommandObjectPlugin.cpp:285:24
frame #58: 0x000000012a8f8134 LLDB`CommandObjectPluginEnable::DoExecute(this=0x0000000c6f8748c0, command=0x000000016d1d0db0, result=0x000000016d1d1810) at CommandObjectPlugin.cpp:316:5
frame #59: 0x000000012a546500 LLDB`lldb_private::CommandObjectParsed::Execute(this=0x0000000c6f8748c0, args_string="instrumentation-runtime.BoundsSafety", result=0x000000016d1d1810) at CommandObject.cpp:830:9
frame #60: 0x000000012a519238 LLDB`lldb_private::CommandInterpreter::HandleCommand(this=0x0000000c6ed28000, command_line="plugin enable instrumentation-runtime.BoundsSafety", lazy_add_to_history=eLazyBoolCalculate, result=0x000000016d1d1810, force_repeat_command=false) at CommandInterpreter.cpp:2300:14
frame #61: 0x000000012a51da9c LLDB`lldb_private::CommandInterpreter::IOHandlerInputComplete(this=0x0000000c6ed28000, io_handler=0x0000000c6e85e718, line="plugin enable instrumentation-runtime.BoundsSafety") at CommandInterpreter.cpp:3401:3
frame #62: 0x000000012a369ebc LLDB`lldb_private::IOHandlerEditline::Run(this=0x0000000c6e85e718) at IOHandler.cpp:609:22
frame #63: 0x000000012a30ba38 LLDB`lldb_private::Debugger::RunIOHandlers(this=0x0000000103e55420) at Debugger.cpp:1331:16
frame #64: 0x000000012a51f204 LLDB`lldb_private::CommandInterpreter::RunCommandInterpreter(this=0x0000000c6ed28000, options=0x000000016d1d1bdc) at CommandInterpreter.cpp:3693:16
frame #65: 0x0000000124e252c8 LLDB`lldb::SBDebugger::RunCommandInterpreter(this=0x000000016d1d2140, auto_handle_events=true, spawn_thread=false) at SBDebugger.cpp:1188:42
frame #66: 0x0000000102c3320c lldb`Driver::MainLoop(this=0x000000016d1d2120) at Driver.cpp:636:18
frame #67: 0x0000000102c33ae8 lldb`main(argc=4, argv=0x000000016d1d2f18) at Driver.cpp:851:26
frame #68: 0x0000000182a35d54 dyld`start + 7184
(lldb)
```
https://github.com/llvm/llvm-project/pull/190083
More information about the lldb-commits
mailing list