Index: lldb/bindings/interface/SBModule.i =================================================================== --- lldb/bindings/interface/SBModule.i +++ lldb/bindings/interface/SBModule.i @@ -353,6 +353,17 @@ static uint32_t GetNumberAllocatedModules(); + %feature("docstring", " + Removes all modules which are no longer needed by any part of LLDB from + the module cache. + + This is an implementation detail exposed for testing and should not be + relied upon. Use SBDebugger::MemoryPressureDetected instead to reduce + LLDB's memory consumption during execution. + ") ClearCachedModules; + static void + ClearCachedModules(); + STRING_EXTENSION(SBModule) #ifdef SWIGPYTHON Index: lldb/include/lldb/API/SBModule.h =================================================================== --- lldb/include/lldb/API/SBModule.h +++ lldb/include/lldb/API/SBModule.h @@ -291,6 +291,8 @@ /// Get the number of global modules. static uint32_t GetNumberAllocatedModules(); + static void ClearCachedModules(); + private: friend class SBAddress; friend class SBFrame; Index: lldb/packages/Python/lldbsuite/test/lldbtest.py =================================================================== --- lldb/packages/Python/lldbsuite/test/lldbtest.py +++ lldb/packages/Python/lldbsuite/test/lldbtest.py @@ -1058,6 +1058,17 @@ lldb.SBDebugger.Destroy(self.dbg) del self.dbg + # All modules should be orphaned now so that they can be cleared from + # the shared module cache. + lldb.SBModule.ClearCachedModules() + + # Modules are not orphaned during reproducer replay because they're + # leaked on purpose. + if not configuration.is_reproducer(): + # Assert that the global module cache is empty. + self.assertEqual(lldb.SBModule.GetNumberAllocatedModules(), 0) + + # ========================================================= # Various callbacks to allow introspection of test progress # ========================================================= @@ -2021,13 +2032,9 @@ for target in targets: self.dbg.DeleteTarget(target) - # Modules are not orphaned during reproducer replay because they're - # leaked on purpose. if not configuration.is_reproducer(): # Assert that all targets are deleted. - assert self.dbg.GetNumTargets() == 0 - # Assert that the global module cache is empty. - assert lldb.SBModule.GetNumberAllocatedModules() == 0 + self.assertEqual(self.dbg.GetNumTargets(), 0) # Do this last, to make sure it's in reverse order from how we setup. Base.tearDown(self) Index: lldb/source/API/SBModule.cpp =================================================================== --- lldb/source/API/SBModule.cpp +++ lldb/source/API/SBModule.cpp @@ -690,6 +690,13 @@ return Module::GetNumberAllocatedModules(); } +void SBModule::ClearCachedModules() { + LLDB_RECORD_STATIC_METHOD_NO_ARGS(void, SBModule, + ClearCachedModules); + const bool mandatory = false; + ModuleList::RemoveOrphanSharedModules(mandatory); +} + namespace lldb_private { namespace repro {