[Lldb-commits] [lldb] r336824 - Allow specifying an exit code for the 'quit' command

Raphael Isemann via lldb-commits lldb-commits at lists.llvm.org
Wed Jul 11 10:18:01 PDT 2018


Author: teemperor
Date: Wed Jul 11 10:18:01 2018
New Revision: 336824

URL: http://llvm.org/viewvc/llvm-project?rev=336824&view=rev
Log:
Allow specifying an exit code for the 'quit' command

Summary:
This patch adds the possibility to specify an exit code when calling quit.
We accept any int, even though it depends on the user what happens if the int is
out of the range of what the operating system supports as exit codes.

Fixes rdar://problem/38452312

Reviewers: davide, jingham, clayborg

Reviewed By: jingham

Subscribers: clayborg, jingham, lldb-commits

Differential Revision: https://reviews.llvm.org/D48659

Added:
    lldb/trunk/lit/Quit/
    lldb/trunk/lit/Quit/TestQuitExitCode-30.test
    lldb/trunk/lit/Quit/TestQuitExitCode0.test
    lldb/trunk/lit/Quit/TestQuitExitCode30.test
    lldb/trunk/lit/Quit/TestQuitExitCodeHex0.test
    lldb/trunk/lit/Quit/TestQuitExitCodeHexA.test
    lldb/trunk/lit/Quit/TestQuitExitCodeImplicit0.test
    lldb/trunk/lit/Quit/TestQuitExitCodeNonInt.test
    lldb/trunk/lit/Quit/TestQuitExitCodeTooManyArgs.test
    lldb/trunk/lit/Quit/expect_exit_code.py   (with props)
    lldb/trunk/lit/Quit/lit.local.cfg
    lldb/trunk/packages/Python/lldbsuite/test/quit/
    lldb/trunk/packages/Python/lldbsuite/test/quit/TestQuit.py
Modified:
    lldb/trunk/include/lldb/API/SBCommandInterpreter.h
    lldb/trunk/include/lldb/Interpreter/CommandInterpreter.h
    lldb/trunk/scripts/interface/SBCommandInterpreter.i
    lldb/trunk/source/API/SBCommandInterpreter.cpp
    lldb/trunk/source/Commands/CommandObjectQuit.cpp
    lldb/trunk/source/Interpreter/CommandInterpreter.cpp
    lldb/trunk/tools/driver/Driver.cpp
    lldb/trunk/tools/driver/Driver.h

Modified: lldb/trunk/include/lldb/API/SBCommandInterpreter.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBCommandInterpreter.h?rev=336824&r1=336823&r2=336824&view=diff
==============================================================================
--- lldb/trunk/include/lldb/API/SBCommandInterpreter.h (original)
+++ lldb/trunk/include/lldb/API/SBCommandInterpreter.h Wed Jul 11 10:18:01 2018
@@ -208,6 +208,25 @@ public:
   void SetPromptOnQuit(bool b);
 
   //----------------------------------------------------------------------
+  /// Sets whether the command interpreter should allow custom exit codes
+  /// for the 'quit' command.
+  //----------------------------------------------------------------------
+  void AllowExitCodeOnQuit(bool allow);
+
+  //----------------------------------------------------------------------
+  /// Returns true if the user has called the 'quit' command with a custom exit
+  /// code.
+  //----------------------------------------------------------------------
+  bool HasCustomQuitExitCode();
+
+  //----------------------------------------------------------------------
+  /// Returns the exit code that the user has specified when running the
+  /// 'quit' command. Returns 0 if the user hasn't called 'quit' at all or
+  /// without a custom exit code.
+  //----------------------------------------------------------------------
+  int GetQuitStatus();
+
+  //----------------------------------------------------------------------
   /// Resolve the command just as HandleCommand would, expanding abbreviations
   /// and aliases.  If successful, result->GetOutput has the full expansion.
   //----------------------------------------------------------------------

Modified: lldb/trunk/include/lldb/Interpreter/CommandInterpreter.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Interpreter/CommandInterpreter.h?rev=336824&r1=336823&r2=336824&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Interpreter/CommandInterpreter.h (original)
+++ lldb/trunk/include/lldb/Interpreter/CommandInterpreter.h Wed Jul 11 10:18:01 2018
@@ -455,6 +455,30 @@ public:
 
   void SetPromptOnQuit(bool b);
 
+  //------------------------------------------------------------------
+  /// Specify if the command interpreter should allow that the user can
+  /// specify a custom exit code when calling 'quit'.
+  //------------------------------------------------------------------
+  void AllowExitCodeOnQuit(bool allow);
+
+  //------------------------------------------------------------------
+  /// Sets the exit code for the quit command.
+  /// @param[in] exit_code
+  ///     The exit code that the driver should return on exit.
+  /// @return True if the exit code was successfully set; false if the
+  ///         interpreter doesn't allow custom exit codes.
+  /// @see AllowExitCodeOnQuit
+  //------------------------------------------------------------------
+  LLVM_NODISCARD bool SetQuitExitCode(int exit_code);
+
+  //------------------------------------------------------------------
+  /// Returns the exit code that the user has specified when running the
+  /// 'quit' command.
+  /// @param[out] exited
+  ///     Set to true if the user has called quit with a custom exit code.
+  //------------------------------------------------------------------
+  int GetQuitExitCode(bool &exited) const;
+
   void ResolveCommand(const char *command_line, CommandReturnObject &result);
 
   bool GetStopCmdSourceOnError() const;
@@ -558,6 +582,12 @@ private:
   uint32_t m_num_errors;
   bool m_quit_requested;
   bool m_stopped_for_crash;
+
+  // The exit code the user has requested when calling the 'quit' command.
+  // No value means the user hasn't set a custom exit code so far.
+  llvm::Optional<int> m_quit_exit_code;
+  // If the driver is accepts custom exit codes for the 'quit' command.
+  bool m_allow_exit_code = false;
 };
 
 } // namespace lldb_private

Added: lldb/trunk/lit/Quit/TestQuitExitCode-30.test
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lit/Quit/TestQuitExitCode-30.test?rev=336824&view=auto
==============================================================================
--- lldb/trunk/lit/Quit/TestQuitExitCode-30.test (added)
+++ lldb/trunk/lit/Quit/TestQuitExitCode-30.test Wed Jul 11 10:18:01 2018
@@ -0,0 +1,3 @@
+# UNSUPPORTED: windows
+# RUN: python %S/expect_exit_code.py 226 %lldb -b -s %s
+q -30

Added: lldb/trunk/lit/Quit/TestQuitExitCode0.test
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lit/Quit/TestQuitExitCode0.test?rev=336824&view=auto
==============================================================================
--- lldb/trunk/lit/Quit/TestQuitExitCode0.test (added)
+++ lldb/trunk/lit/Quit/TestQuitExitCode0.test Wed Jul 11 10:18:01 2018
@@ -0,0 +1,3 @@
+# UNSUPPORTED: windows
+# RUN: %lldb -b -s %s
+q 0

Added: lldb/trunk/lit/Quit/TestQuitExitCode30.test
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lit/Quit/TestQuitExitCode30.test?rev=336824&view=auto
==============================================================================
--- lldb/trunk/lit/Quit/TestQuitExitCode30.test (added)
+++ lldb/trunk/lit/Quit/TestQuitExitCode30.test Wed Jul 11 10:18:01 2018
@@ -0,0 +1,3 @@
+# UNSUPPORTED: windows
+# RUN: python %S/expect_exit_code.py 30  %lldb -b -s %s
+q 30

Added: lldb/trunk/lit/Quit/TestQuitExitCodeHex0.test
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lit/Quit/TestQuitExitCodeHex0.test?rev=336824&view=auto
==============================================================================
--- lldb/trunk/lit/Quit/TestQuitExitCodeHex0.test (added)
+++ lldb/trunk/lit/Quit/TestQuitExitCodeHex0.test Wed Jul 11 10:18:01 2018
@@ -0,0 +1,3 @@
+# UNSUPPORTED: windows
+# RUN: %lldb -b -s %s
+q 0x0

Added: lldb/trunk/lit/Quit/TestQuitExitCodeHexA.test
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lit/Quit/TestQuitExitCodeHexA.test?rev=336824&view=auto
==============================================================================
--- lldb/trunk/lit/Quit/TestQuitExitCodeHexA.test (added)
+++ lldb/trunk/lit/Quit/TestQuitExitCodeHexA.test Wed Jul 11 10:18:01 2018
@@ -0,0 +1,3 @@
+# UNSUPPORTED: windows
+# RUN: python %S/expect_exit_code.py 10 %lldb -b -s %s
+q 0xA

Added: lldb/trunk/lit/Quit/TestQuitExitCodeImplicit0.test
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lit/Quit/TestQuitExitCodeImplicit0.test?rev=336824&view=auto
==============================================================================
--- lldb/trunk/lit/Quit/TestQuitExitCodeImplicit0.test (added)
+++ lldb/trunk/lit/Quit/TestQuitExitCodeImplicit0.test Wed Jul 11 10:18:01 2018
@@ -0,0 +1,3 @@
+# UNSUPPORTED: windows
+# RUN: %lldb -b -s %s
+q

Added: lldb/trunk/lit/Quit/TestQuitExitCodeNonInt.test
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lit/Quit/TestQuitExitCodeNonInt.test?rev=336824&view=auto
==============================================================================
--- lldb/trunk/lit/Quit/TestQuitExitCodeNonInt.test (added)
+++ lldb/trunk/lit/Quit/TestQuitExitCodeNonInt.test Wed Jul 11 10:18:01 2018
@@ -0,0 +1,4 @@
+# UNSUPPORTED: windows
+# RUN: %lldb -b -s %s 2>&1 | FileCheck %s
+q str
+// CHECK: Couldn't parse 'str'

Added: lldb/trunk/lit/Quit/TestQuitExitCodeTooManyArgs.test
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lit/Quit/TestQuitExitCodeTooManyArgs.test?rev=336824&view=auto
==============================================================================
--- lldb/trunk/lit/Quit/TestQuitExitCodeTooManyArgs.test (added)
+++ lldb/trunk/lit/Quit/TestQuitExitCodeTooManyArgs.test Wed Jul 11 10:18:01 2018
@@ -0,0 +1,4 @@
+# UNSUPPORTED: windows
+# RUN: %lldb -b -s %s 2>&1 | FileCheck %s
+q 1 2
+// CHECK: Too many arguments for 'quit'

Added: lldb/trunk/lit/Quit/expect_exit_code.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lit/Quit/expect_exit_code.py?rev=336824&view=auto
==============================================================================
--- lldb/trunk/lit/Quit/expect_exit_code.py (added)
+++ lldb/trunk/lit/Quit/expect_exit_code.py Wed Jul 11 10:18:01 2018
@@ -0,0 +1,16 @@
+#!/usr/bin/env python2
+
+import subprocess
+import sys
+
+args = sys.argv
+
+expected_exit_code = args[1]
+
+args = args[2:]
+print("Running " + (" ".join(args)))
+real_exit_code = subprocess.call(args)
+
+if str(real_exit_code) != expected_exit_code:
+  print("Got exit code %d but expected %s" % (real_exit_code, expected_exit_code))
+  exit(1)

Propchange: lldb/trunk/lit/Quit/expect_exit_code.py
------------------------------------------------------------------------------
    svn:executable = *

Added: lldb/trunk/lit/Quit/lit.local.cfg
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lit/Quit/lit.local.cfg?rev=336824&view=auto
==============================================================================
--- lldb/trunk/lit/Quit/lit.local.cfg (added)
+++ lldb/trunk/lit/Quit/lit.local.cfg Wed Jul 11 10:18:01 2018
@@ -0,0 +1 @@
+config.suffixes = ['.test']

Added: lldb/trunk/packages/Python/lldbsuite/test/quit/TestQuit.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/quit/TestQuit.py?rev=336824&view=auto
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/quit/TestQuit.py (added)
+++ lldb/trunk/packages/Python/lldbsuite/test/quit/TestQuit.py Wed Jul 11 10:18:01 2018
@@ -0,0 +1,32 @@
+"""
+Test lldb's quit command.
+"""
+
+from __future__ import print_function
+
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class QuitCommandTestCase(TestBase):
+
+    mydir = TestBase.compute_mydir(__file__)
+
+    @no_debug_info_test
+    def test_quit_exit_code_disallow(self):
+        self.ci.AllowExitCodeOnQuit(False)
+        self.expect(
+            "quit 20",
+            substrs=[
+                "error: The current driver doesn't allow custom exit codes for the quit command"],
+            error=True)
+        self.assertFalse(self.ci.HasCustomQuitExitCode())
+
+    @no_debug_info_test
+    def test_quit_exit_code_allow(self):
+        self.ci.AllowExitCodeOnQuit(True)
+        self.runCmd("quit 10", check=False)
+        self.assertTrue(self.ci.HasCustomQuitExitCode())
+        self.assertEqual(self.ci.GetQuitStatus(), 10)

Modified: lldb/trunk/scripts/interface/SBCommandInterpreter.i
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/scripts/interface/SBCommandInterpreter.i?rev=336824&r1=336823&r2=336824&view=diff
==============================================================================
--- lldb/trunk/scripts/interface/SBCommandInterpreter.i (original)
+++ lldb/trunk/scripts/interface/SBCommandInterpreter.i Wed Jul 11 10:18:01 2018
@@ -156,6 +156,15 @@ public:
     SetPromptOnQuit(bool b);
 
     void
+    AllowExitCodeOnQuit(bool b);
+
+    bool
+    HasCustomQuitExitCode();
+
+    int
+    GetQuitStatus();
+
+    void
     ResolveCommand(const char *command_line, SBCommandReturnObject &result);
 
     bool

Modified: lldb/trunk/source/API/SBCommandInterpreter.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SBCommandInterpreter.cpp?rev=336824&r1=336823&r2=336824&view=diff
==============================================================================
--- lldb/trunk/source/API/SBCommandInterpreter.cpp (original)
+++ lldb/trunk/source/API/SBCommandInterpreter.cpp Wed Jul 11 10:18:01 2018
@@ -379,6 +379,23 @@ void SBCommandInterpreter::SetPromptOnQu
     m_opaque_ptr->SetPromptOnQuit(b);
 }
 
+void SBCommandInterpreter::AllowExitCodeOnQuit(bool allow) {
+  if (m_opaque_ptr)
+    m_opaque_ptr->AllowExitCodeOnQuit(allow);
+}
+
+bool SBCommandInterpreter::HasCustomQuitExitCode() {
+  bool exited = false;
+  if (m_opaque_ptr)
+    m_opaque_ptr->GetQuitExitCode(exited);
+  return exited;
+}
+
+int SBCommandInterpreter::GetQuitStatus() {
+  bool exited = false;
+  return (m_opaque_ptr ? m_opaque_ptr->GetQuitExitCode(exited) : 0);
+}
+
 void SBCommandInterpreter::ResolveCommand(const char *command_line,
                                           SBCommandReturnObject &result) {
   result.Clear();

Modified: lldb/trunk/source/Commands/CommandObjectQuit.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectQuit.cpp?rev=336824&r1=336823&r2=336824&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectQuit.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectQuit.cpp Wed Jul 11 10:18:01 2018
@@ -16,6 +16,7 @@
 #include "lldb/Interpreter/CommandInterpreter.h"
 #include "lldb/Interpreter/CommandReturnObject.h"
 #include "lldb/Target/Process.h"
+#include "lldb/Utility/StreamString.h"
 
 using namespace lldb;
 using namespace lldb_private;
@@ -26,7 +27,7 @@ using namespace lldb_private;
 
 CommandObjectQuit::CommandObjectQuit(CommandInterpreter &interpreter)
     : CommandObjectParsed(interpreter, "quit", "Quit the LLDB debugger.",
-                          "quit") {}
+                          "quit [exit-code]") {}
 
 CommandObjectQuit::~CommandObjectQuit() {}
 
@@ -77,6 +78,41 @@ bool CommandObjectQuit::DoExecute(Args &
       return false;
     }
   }
+
+  if (command.GetArgumentCount() > 1) {
+    result.AppendError("Too many arguments for 'quit'. Only an optional exit "
+                       "code is allowed");
+    result.SetStatus(eReturnStatusFailed);
+    return false;
+  }
+
+  if (command.GetArgumentCount() > 1) {
+    result.AppendError("Too many arguments for 'quit'. Only an optional exit "
+                       "code is allowed");
+    result.SetStatus(eReturnStatusFailed);
+    return false;
+  }
+
+  // We parse the exit code argument if there is one.
+  if (command.GetArgumentCount() == 1) {
+    llvm::StringRef arg = command.GetArgumentAtIndex(0);
+    int exit_code;
+    if (arg.getAsInteger(/*autodetect radix*/ 0, exit_code)) {
+      lldb_private::StreamString s;
+      std::string arg_str = arg.str();
+      s.Printf("Couldn't parse '%s' as integer for exit code.", arg_str.data());
+      result.AppendError(s.GetString());
+      result.SetStatus(eReturnStatusFailed);
+      return false;
+    }
+    if (!m_interpreter.SetQuitExitCode(exit_code)) {
+      result.AppendError("The current driver doesn't allow custom exit codes"
+                         " for the quit command.");
+      result.SetStatus(eReturnStatusFailed);
+      return false;
+    }
+  }
+
   const uint32_t event_type =
       CommandInterpreter::eBroadcastBitQuitCommandReceived;
   m_interpreter.BroadcastEvent(event_type);

Modified: lldb/trunk/source/Interpreter/CommandInterpreter.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/CommandInterpreter.cpp?rev=336824&r1=336823&r2=336824&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/CommandInterpreter.cpp (original)
+++ lldb/trunk/source/Interpreter/CommandInterpreter.cpp Wed Jul 11 10:18:01 2018
@@ -144,6 +144,26 @@ void CommandInterpreter::SetPromptOnQuit
   m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
 }
 
+void CommandInterpreter::AllowExitCodeOnQuit(bool allow) {
+  m_allow_exit_code = allow;
+  if (!allow)
+    m_quit_exit_code.reset();
+}
+
+bool CommandInterpreter::SetQuitExitCode(int exit_code) {
+  if (!m_allow_exit_code)
+    return false;
+  m_quit_exit_code = exit_code;
+  return true;
+}
+
+int CommandInterpreter::GetQuitExitCode(bool &exited) const {
+  exited = m_quit_exit_code.hasValue();
+  if (exited)
+    return *m_quit_exit_code;
+  return 0;
+}
+
 void CommandInterpreter::ResolveCommand(const char *command_line,
                                         CommandReturnObject &result) {
   std::string command = command_line;

Modified: lldb/trunk/tools/driver/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/driver/Driver.cpp?rev=336824&r1=336823&r2=336824&view=diff
==============================================================================
--- lldb/trunk/tools/driver/Driver.cpp (original)
+++ lldb/trunk/tools/driver/Driver.cpp Wed Jul 11 10:18:01 2018
@@ -962,7 +962,7 @@ std::string EscapeString(std::string arg
   return '"' + arg + '"';
 }
 
-void Driver::MainLoop() {
+int Driver::MainLoop() {
   if (::tcgetattr(STDIN_FILENO, &g_old_stdin_termios) == 0) {
     g_old_stdin_termios_is_valid = true;
     atexit(reset_stdin_termios);
@@ -1001,6 +1001,10 @@ void Driver::MainLoop() {
     result.PutOutput(m_debugger.GetOutputFileHandle());
   }
 
+  // We allow the user to specify an exit code when calling quit which we will
+  // return when exiting.
+  m_debugger.GetCommandInterpreter().AllowExitCodeOnQuit(true);
+
   // Now we handle options we got from the command line
   SBStream commands_stream;
 
@@ -1159,7 +1163,9 @@ void Driver::MainLoop() {
   reset_stdin_termios();
   fclose(stdin);
 
+  int exit_code = sb_interpreter.GetQuitStatus();
   SBDebugger::Destroy(m_debugger);
+  return exit_code;
 }
 
 void Driver::ResizeWindow(unsigned short col) {
@@ -1237,6 +1243,7 @@ main(int argc, char const *argv[])
   signal(SIGCONT, sigcont_handler);
 #endif
 
+  int exit_code = 0;
   // Create a scope for driver so that the driver object will destroy itself
   // before SBDebugger::Terminate() is called.
   {
@@ -1245,14 +1252,15 @@ main(int argc, char const *argv[])
     bool exiting = false;
     SBError error(driver.ParseArgs(argc, argv, stdout, exiting));
     if (error.Fail()) {
+      exit_code = 1;
       const char *error_cstr = error.GetCString();
       if (error_cstr)
         ::fprintf(stderr, "error: %s\n", error_cstr);
     } else if (!exiting) {
-      driver.MainLoop();
+      exit_code = driver.MainLoop();
     }
   }
 
   SBDebugger::Terminate();
-  return 0;
+  return exit_code;
 }

Modified: lldb/trunk/tools/driver/Driver.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/driver/Driver.h?rev=336824&r1=336823&r2=336824&view=diff
==============================================================================
--- lldb/trunk/tools/driver/Driver.h (original)
+++ lldb/trunk/tools/driver/Driver.h Wed Jul 11 10:18:01 2018
@@ -37,7 +37,10 @@ public:
 
   virtual ~Driver();
 
-  void MainLoop();
+  /// Runs the main loop.
+  ///
+  /// @return The exit code that the process should return.
+  int MainLoop();
 
   lldb::SBError ParseArgs(int argc, const char *argv[], FILE *out_fh,
                           bool &do_exit);




More information about the lldb-commits mailing list