[Lldb-commits] [lldb] r259964 - Fix an issue where certain CommandObjects (or Options thereof) were being created once, bound to a specific CommandInterpreter (and hence a specific Debugger), and then cached for reuse across different Debugger instances

Enrico Granata via lldb-commits lldb-commits at lists.llvm.org
Fri Feb 5 16:43:07 PST 2016


Author: enrico
Date: Fri Feb  5 18:43:07 2016
New Revision: 259964

URL: http://llvm.org/viewvc/llvm-project?rev=259964&view=rev
Log:
Fix an issue where certain CommandObjects (or Options thereof) were being created once, bound to a specific CommandInterpreter (and hence a specific Debugger), and then cached for reuse across different Debugger instances

Obviously, if the original Debugger goes away, those commands are holding on to now stale memory, which has the potential to cause crashes

Fixes rdar://24460882


Added:
    lldb/trunk/packages/Python/lldbsuite/test/functionalities/multidebugger_commands/
    lldb/trunk/packages/Python/lldbsuite/test/functionalities/multidebugger_commands/TestMultipleDebuggersCommands.py
Modified:
    lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp
    lldb/trunk/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
    lldb/trunk/source/Plugins/Platform/POSIX/PlatformPOSIX.h
    lldb/trunk/source/Target/LanguageRuntime.cpp

Added: lldb/trunk/packages/Python/lldbsuite/test/functionalities/multidebugger_commands/TestMultipleDebuggersCommands.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/functionalities/multidebugger_commands/TestMultipleDebuggersCommands.py?rev=259964&view=auto
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/functionalities/multidebugger_commands/TestMultipleDebuggersCommands.py (added)
+++ lldb/trunk/packages/Python/lldbsuite/test/functionalities/multidebugger_commands/TestMultipleDebuggersCommands.py Fri Feb  5 18:43:07 2016
@@ -0,0 +1,48 @@
+"""
+Test that commands do not try and hold on to stale CommandInterpreters in a multiple debuggers scenario
+"""
+
+from __future__ import print_function
+
+
+
+import os, time
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+class MultipleDebuggersCommandsTestCase(TestBase):
+
+    mydir = TestBase.compute_mydir(__file__)
+
+    @no_debug_info_test
+    def test_multipledebuggers_commands(self):
+        """Test that commands do not try and hold on to stale CommandInterpreters in a multiple debuggers scenario"""
+        source_init_files = False
+        magic_text = "The following built-in commands may relate to 'env'"
+        
+        debugger_1 = lldb.SBDebugger.Create(source_init_files)
+        interpreter_1 = debugger_1.GetCommandInterpreter()
+        
+        retobj = lldb.SBCommandReturnObject()
+        interpreter_1.HandleCommand("apropos env", retobj)
+        self.assertTrue(magic_text in str(retobj), "[interpreter_1]: the output does not contain the correct words")
+        
+        if self.TraceOn(): print(str(retobj))
+        
+        lldb.SBDebugger.Destroy(debugger_1)
+        
+        # now do this again with a different debugger - we shouldn't crash
+        
+        debugger_2 = lldb.SBDebugger.Create(source_init_files)
+        interpreter_2 = debugger_2.GetCommandInterpreter()
+        
+        retobj = lldb.SBCommandReturnObject()
+        interpreter_2.HandleCommand("apropos env", retobj)
+        self.assertTrue(magic_text in str(retobj), "[interpreter_2]: the output does not contain the correct words")
+        
+        if self.TraceOn(): print(str(retobj))
+        
+        lldb.SBDebugger.Destroy(debugger_2)
+        

Modified: lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp?rev=259964&r1=259963&r2=259964&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp (original)
+++ lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp Fri Feb  5 18:43:07 2016
@@ -4167,12 +4167,7 @@ RenderScriptRuntime::RenderScriptRuntime
 lldb::CommandObjectSP
 RenderScriptRuntime::GetCommandObject(lldb_private::CommandInterpreter &interpreter)
 {
-    static CommandObjectSP command_object;
-    if (!command_object)
-    {
-        command_object.reset(new CommandObjectRenderScriptRuntime(interpreter));
-    }
-    return command_object;
+    return CommandObjectSP(new CommandObjectRenderScriptRuntime(interpreter));
 }
 
 RenderScriptRuntime::~RenderScriptRuntime() = default;

Modified: lldb/trunk/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp?rev=259964&r1=259963&r2=259964&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp (original)
+++ lldb/trunk/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp Fri Feb  5 18:43:07 2016
@@ -41,6 +41,9 @@ using namespace lldb_private;
 //------------------------------------------------------------------
 PlatformPOSIX::PlatformPOSIX (bool is_host) :
 Platform(is_host),  // This is the local host platform
+m_option_group_platform_rsync(new OptionGroupPlatformRSync()),
+m_option_group_platform_ssh(new OptionGroupPlatformSSH()),
+m_option_group_platform_caching(new OptionGroupPlatformCaching()),
 m_remote_platform_sp ()
 {
 }
@@ -69,14 +72,17 @@ PlatformPOSIX::GetModuleSpec (const File
 lldb_private::OptionGroupOptions*
 PlatformPOSIX::GetConnectionOptions (lldb_private::CommandInterpreter& interpreter)
 {
-    if (m_options.get() == NULL)
+    auto iter = m_options.find(&interpreter), end = m_options.end();
+    if (iter == end)
     {
-        m_options.reset(new OptionGroupOptions(interpreter));
-        m_options->Append(new OptionGroupPlatformRSync());
-        m_options->Append(new OptionGroupPlatformSSH());
-        m_options->Append(new OptionGroupPlatformCaching());
+        std::unique_ptr<lldb_private::OptionGroupOptions> options(new OptionGroupOptions(interpreter));
+        options->Append(m_option_group_platform_rsync.get());
+        options->Append(m_option_group_platform_ssh.get());
+        options->Append(m_option_group_platform_caching.get());
+        m_options[&interpreter] = std::move(options);
     }
-    return m_options.get();
+    
+    return m_options.at(&interpreter).get();
 }
 
 bool
@@ -675,29 +681,21 @@ PlatformPOSIX::ConnectRemote (Args& args
 
     if (error.Success() && m_remote_platform_sp)
     {
-        if (m_options.get())
+        if (m_option_group_platform_rsync.get() && m_option_group_platform_ssh.get() && m_option_group_platform_caching.get())
         {
-            OptionGroupOptions* options = m_options.get();
-            const OptionGroupPlatformRSync *m_rsync_options =
-                static_cast<const OptionGroupPlatformRSync *>(options->GetGroupWithOption('r'));
-            const OptionGroupPlatformSSH *m_ssh_options =
-                static_cast<const OptionGroupPlatformSSH *>(options->GetGroupWithOption('s'));
-            const OptionGroupPlatformCaching *m_cache_options =
-                static_cast<const OptionGroupPlatformCaching *>(options->GetGroupWithOption('c'));
-
-            if (m_rsync_options->m_rsync)
+            if (m_option_group_platform_rsync->m_rsync)
             {
                 SetSupportsRSync(true);
-                SetRSyncOpts(m_rsync_options->m_rsync_opts.c_str());
-                SetRSyncPrefix(m_rsync_options->m_rsync_prefix.c_str());
-                SetIgnoresRemoteHostname(m_rsync_options->m_ignores_remote_hostname);
+                SetRSyncOpts(m_option_group_platform_rsync->m_rsync_opts.c_str());
+                SetRSyncPrefix(m_option_group_platform_rsync->m_rsync_prefix.c_str());
+                SetIgnoresRemoteHostname(m_option_group_platform_rsync->m_ignores_remote_hostname);
             }
-            if (m_ssh_options->m_ssh)
+            if (m_option_group_platform_ssh->m_ssh)
             {
                 SetSupportsSSH(true);
-                SetSSHOpts(m_ssh_options->m_ssh_opts.c_str());
+                SetSSHOpts(m_option_group_platform_ssh->m_ssh_opts.c_str());
             }
-            SetLocalCacheDirectory(m_cache_options->m_cache_dir.c_str());
+            SetLocalCacheDirectory(m_option_group_platform_caching->m_cache_dir.c_str());
         }
     }
 

Modified: lldb/trunk/source/Plugins/Platform/POSIX/PlatformPOSIX.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Platform/POSIX/PlatformPOSIX.h?rev=259964&r1=259963&r2=259964&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Platform/POSIX/PlatformPOSIX.h (original)
+++ lldb/trunk/source/Plugins/Platform/POSIX/PlatformPOSIX.h Fri Feb  5 18:43:07 2016
@@ -12,6 +12,7 @@
 
 // C Includes
 // C++ Includes
+#include <map>
 #include <memory>
 
 // Other libraries and framework includes
@@ -192,7 +193,11 @@ public:
     ConnectToWaitingProcesses(lldb_private::Debugger& debugger, lldb_private::Error& error) override;
 
 protected:
-    std::unique_ptr<lldb_private::OptionGroupOptions> m_options;
+    std::unique_ptr<lldb_private::OptionGroupPlatformRSync> m_option_group_platform_rsync;
+    std::unique_ptr<lldb_private::OptionGroupPlatformSSH> m_option_group_platform_ssh;
+    std::unique_ptr<lldb_private::OptionGroupPlatformCaching> m_option_group_platform_caching;
+    
+    std::map<lldb_private::CommandInterpreter*,std::unique_ptr<lldb_private::OptionGroupOptions>> m_options;
     lldb::PlatformSP m_remote_platform_sp; // Allow multiple ways to connect to a remote POSIX-compliant OS
 
     lldb_private::Error

Modified: lldb/trunk/source/Target/LanguageRuntime.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/LanguageRuntime.cpp?rev=259964&r1=259963&r2=259964&view=diff
==============================================================================
--- lldb/trunk/source/Target/LanguageRuntime.cpp (original)
+++ lldb/trunk/source/Target/LanguageRuntime.cpp Fri Feb  5 18:43:07 2016
@@ -336,6 +336,10 @@ LanguageRuntime::InitializeCommands (Com
             CommandObjectSP command = command_callback(parent->GetCommandInterpreter());
             if (command)
             {
+                // the CommandObject vended by a Language plugin cannot be created once and cached because
+                // we may create multiple debuggers and need one instance of the command each - the implementing function
+                // is meant to create a new instance of the command each time it is invoked
+                assert(&command->GetCommandInterpreter() == &parent->GetCommandInterpreter() && "language plugin returned command for a mismatched CommandInterpreter");
                 parent->LoadSubCommand(command->GetCommandName(), command);
             }
         }




More information about the lldb-commits mailing list