<rdar://problem/12786725>
authorEnrico Granata <egranata@apple.com>
Thu, 17 Jan 2013 21:36:19 +0000 (21:36 +0000)
committerEnrico Granata <egranata@apple.com>
Thu, 17 Jan 2013 21:36:19 +0000 (21:36 +0000)
If there is any alive process being debugged, the user is asked for confirmation before quitting LLDB
This should prevent situations where the user mistakenly types "q" and LLDB slaughters their process without any mercy whatsoever
Since it can quickly get tedious, there is a new setting on the command interpreter to disable this and replicate the previous behavior

llvm-svn: 172757

lldb/include/lldb/Interpreter/CommandInterpreter.h
lldb/source/Commands/CommandObjectQuit.cpp
lldb/source/Commands/CommandObjectQuit.h
lldb/source/Interpreter/CommandInterpreter.cpp

index aec143b..7c2f302 100644 (file)
@@ -436,6 +436,9 @@ public:
     bool
     GetExpandRegexAliases () const;
     
+    bool
+    GetPromptOnQuit () const;
+
 protected:
     friend class Debugger;
 
index bdccec4..c4c09e8 100644 (file)
@@ -34,9 +34,63 @@ CommandObjectQuit::~CommandObjectQuit ()
 {
 }
 
+// returns true if there is at least one alive process
+// is_a_detach will be true if all alive processes will be detached when you quit
+// and false if at least one process will be killed instead
+bool
+CommandObjectQuit::ShouldAskForConfirmation (bool& is_a_detach)
+{
+    if (m_interpreter.GetPromptOnQuit() == false)
+        return false;
+    bool should_prompt = false;
+    is_a_detach = true;
+    for (uint32_t debugger_idx = 0;
+         debugger_idx < Debugger::GetNumDebuggers();
+         debugger_idx++)
+    {
+        DebuggerSP debugger_sp(Debugger::GetDebuggerAtIndex(debugger_idx));
+        if (!debugger_sp)
+            continue;
+        const TargetList& target_list(debugger_sp->GetTargetList());
+        for (uint32_t target_idx = 0;
+             target_idx < target_list.GetNumTargets();
+             target_idx++)
+        {
+            TargetSP target_sp(target_list.GetTargetAtIndex(target_idx));
+            if (!target_sp)
+                continue;
+            ProcessSP process_sp(target_sp->GetProcessSP());
+            if (process_sp &&
+                process_sp->IsValid() &&
+                process_sp->IsAlive())
+            {
+                should_prompt = true;
+                if (process_sp->GetShouldDetach() == false)
+                {
+                    // if we need to kill at least one process, just say so and return
+                    is_a_detach = false;
+                    return should_prompt;
+                }
+            }
+        }
+    }
+    return should_prompt;
+}
+
 bool
 CommandObjectQuit::DoExecute (Args& command, CommandReturnObject &result)
 {
+    bool is_a_detach = true;
+    if (ShouldAskForConfirmation (is_a_detach))
+    {
+        StreamString message;
+        message.Printf("Quitting LLDB will %s one or more processes. Do you really want to proceed", (is_a_detach ? "detach from" : "kill"));
+        if (!m_interpreter.Confirm(message.GetData(), true))
+        {
+            result.SetStatus(eReturnStatusFailed);
+            return false;
+        }
+    }
     m_interpreter.BroadcastEvent (CommandInterpreter::eBroadcastBitQuitCommandReceived);
     result.SetStatus (eReturnStatusQuit);
     return true;
index 444c192..aab0e26 100644 (file)
@@ -35,6 +35,9 @@ protected:
     virtual bool
     DoExecute (Args& args,
              CommandReturnObject &result);
+    
+    bool
+    ShouldAskForConfirmation (bool& is_a_detach);
 
 };
 
index f248fdf..7dfc5d8 100644 (file)
@@ -72,12 +72,14 @@ static PropertyDefinition
 g_properties[] =
 {
     { "expand-regex-aliases", OptionValue::eTypeBoolean, true, false, NULL, NULL, "If true, regular expression alias commands will show the expanded command that will be executed. This can be used to debug new regular expression alias commands." },
+    { "prompt-on-quit", OptionValue::eTypeBoolean, true, true, NULL, NULL, "If true, LLDB will prompt you before quitting if there are any live processes being debugged. If false, LLDB will quit without asking in any case." },
     { NULL                  , OptionValue::eTypeInvalid, true, 0    , NULL, NULL, NULL }
 };
 
 enum
 {
-    ePropertyExpandRegexAliases = 0
+    ePropertyExpandRegexAliases = 0,
+    ePropertyPromptOnQuit = 1
 };
 
 ConstString &
@@ -121,7 +123,12 @@ CommandInterpreter::GetExpandRegexAliases () const
     return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0);
 }
 
-
+bool
+CommandInterpreter::GetPromptOnQuit () const
+{
+    const uint32_t idx = ePropertyPromptOnQuit;
+    return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0);
+}
 
 void
 CommandInterpreter::Initialize ()