[Lldb-commits] [lldb] 5a27b99 - [lldb] Show progress events in the command line driver

Jonas Devlieghere via lldb-commits lldb-commits at lists.llvm.org
Tue Mar 8 18:26:53 PST 2022


Author: Jonas Devlieghere
Date: 2022-03-08T18:24:26-08:00
New Revision: 5a27b99825a5ba3a7a2eec3d35aea381a3ba9a31

URL: https://github.com/llvm/llvm-project/commit/5a27b99825a5ba3a7a2eec3d35aea381a3ba9a31
DIFF: https://github.com/llvm/llvm-project/commit/5a27b99825a5ba3a7a2eec3d35aea381a3ba9a31.diff

LOG: [lldb] Show progress events in the command line driver

This patch adds support for showing progress events when using lldb on
the command line. It spawns a separate thread that listens for progress
events and prints them to the debugger's output stream.

It's nothing fancy (yet), for now it just prints the progress message.
If we know the total number of items being processed, we prefix the
message with something like [1/100], similar to ninja's output.

This patch doesn't use any fancy terminal manipulation: it uses a simple
carriage return (\r) to bring the cursor to the front of the line and
vt100 escape codes to clear the (rest) of the line.

Differential revision: https://reviews.llvm.org/D120972

Added: 
    

Modified: 
    lldb/include/lldb/Core/Debugger.h
    lldb/source/Core/CoreProperties.td
    lldb/source/Core/Debugger.cpp
    lldb/source/Symbol/LocateSymbolFile.cpp

Removed: 
    


################################################################################
diff  --git a/lldb/include/lldb/Core/Debugger.h b/lldb/include/lldb/Core/Debugger.h
index d801e2d874df4..ec6645986310f 100644
--- a/lldb/include/lldb/Core/Debugger.h
+++ b/lldb/include/lldb/Core/Debugger.h
@@ -329,6 +329,8 @@ class Debugger : public std::enable_shared_from_this<Debugger>,
 
   bool SetUseColor(bool use_color);
 
+  bool GetShowProgress() const;
+
   bool GetUseAutosuggestion() const;
 
   llvm::StringRef GetAutosuggestionAnsiPrefix() const;
@@ -439,6 +441,8 @@ class Debugger : public std::enable_shared_from_this<Debugger>,
                              uint64_t completed, uint64_t total,
                              llvm::Optional<lldb::user_id_t> debugger_id);
 
+  void PrintProgress(const Debugger::ProgressEventData &data);
+
   bool StartEventHandlerThread();
 
   void StopEventHandlerThread();
@@ -466,6 +470,8 @@ class Debugger : public std::enable_shared_from_this<Debugger>,
 
   void HandleThreadEvent(const lldb::EventSP &event_sp);
 
+  void HandleProgressEvent(const lldb::EventSP &event_sp);
+
   // Ensures two threads don't attempt to flush process output in parallel.
   std::mutex m_output_flush_mutex;
   void FlushProcessOutput(Process &process, bool flush_stdout,
@@ -514,6 +520,8 @@ class Debugger : public std::enable_shared_from_this<Debugger>,
   IOHandlerStack m_io_handler_stack;
   std::recursive_mutex m_io_handler_synchronous_mutex;
 
+  llvm::Optional<uint64_t> m_current_event_id;
+
   llvm::StringMap<std::weak_ptr<llvm::raw_ostream>> m_log_streams;
   std::shared_ptr<llvm::raw_ostream> m_log_callback_stream_sp;
   ConstString m_instance_name;

diff  --git a/lldb/source/Core/CoreProperties.td b/lldb/source/Core/CoreProperties.td
index 73539dbafae1f..04e2f4e1060d6 100644
--- a/lldb/source/Core/CoreProperties.td
+++ b/lldb/source/Core/CoreProperties.td
@@ -131,6 +131,10 @@ let Definition = "debugger" in {
     Global,
     DefaultTrue,
     Desc<"Whether to use Ansi color codes or not.">;
+  def ShowProgress: Property<"show-progress", "Boolean">,
+    Global,
+    DefaultTrue,
+    Desc<"Whether to show progress or not if the debugger's output is an interactive color-enabled terminal.">;
   def UseSourceCache: Property<"use-source-cache", "Boolean">,
     Global,
     DefaultTrue,

diff  --git a/lldb/source/Core/Debugger.cpp b/lldb/source/Core/Debugger.cpp
index eb0f6b5371d6b..4df7c9800d750 100644
--- a/lldb/source/Core/Debugger.cpp
+++ b/lldb/source/Core/Debugger.cpp
@@ -378,6 +378,12 @@ bool Debugger::SetUseColor(bool b) {
   return ret;
 }
 
+bool Debugger::GetShowProgress() const {
+  const uint32_t idx = ePropertyShowProgress;
+  return m_collection_sp->GetPropertyAtIndexAsBoolean(
+      nullptr, idx, g_debugger_properties[idx].default_uint_value != 0);
+}
+
 bool Debugger::GetUseAutosuggestion() const {
   const uint32_t idx = ePropertyShowAutosuggestion;
   return m_collection_sp->GetPropertyAtIndexAsBoolean(
@@ -1615,6 +1621,11 @@ lldb::thread_result_t Debugger::DefaultEventHandler() {
           CommandInterpreter::eBroadcastBitAsynchronousOutputData |
           CommandInterpreter::eBroadcastBitAsynchronousErrorData);
 
+  if (!m_broadcaster.EventTypeHasListeners(Debugger::eBroadcastBitProgress)) {
+    listener_sp->StartListeningForEvents(&m_broadcaster,
+                                         Debugger::eBroadcastBitProgress);
+  }
+
   // Let the thread that spawned us know that we have started up and that we
   // are now listening to all required events so no events get missed
   m_sync_broadcaster.BroadcastEvent(eBroadcastBitEventThreadIsListening);
@@ -1664,6 +1675,9 @@ lldb::thread_result_t Debugger::DefaultEventHandler() {
                 }
               }
             }
+          } else if (broadcaster == &m_broadcaster) {
+            if (event_type & Debugger::eBroadcastBitProgress)
+              HandleProgressEvent(event_sp);
           }
         }
 
@@ -1729,6 +1743,61 @@ lldb::thread_result_t Debugger::IOHandlerThread() {
   return {};
 }
 
+void Debugger::HandleProgressEvent(const lldb::EventSP &event_sp) {
+  auto *data =
+      Debugger::ProgressEventData::GetEventDataFromEvent(event_sp.get());
+  if (!data)
+    return;
+
+  // Do some bookkeeping for the current event, regardless of whether we're
+  // going to show the progress.
+  const uint64_t id = data->GetID();
+  if (m_current_event_id) {
+    if (id != *m_current_event_id)
+      return;
+    if (data->GetCompleted())
+      m_current_event_id.reset();
+  } else {
+    m_current_event_id = id;
+  }
+
+  // Decide whether we actually are going to show the progress. This decision
+  // can change between iterations so check it inside the loop.
+  if (!GetShowProgress())
+    return;
+
+  // Determine whether the current output file is an interactive terminal with
+  // color support. We assume that if we support ANSI escape codes we support
+  // vt100 escape codes.
+  File &output = GetOutputFile();
+  if (!output.GetIsInteractive() || !output.GetIsTerminalWithColors())
+    return;
+
+  if (data->GetCompleted()) {
+    // Clear the current line.
+    output.Printf("\33[2K\r");
+    return;
+  }
+
+  // Print over previous line, if any.
+  output.Printf("\r");
+
+  // Print the progress message.
+  std::string message = data->GetMessage();
+  if (data->GetTotal() != UINT64_MAX) {
+    output.Printf("[%llu/%llu] %s...", data->GetCompleted(), data->GetTotal(),
+                  message.c_str());
+  } else {
+    output.Printf("%s...", message.c_str());
+  }
+
+  // Clear until the end of the line.
+  output.Printf("\x1B[K");
+
+  // Flush the output.
+  output.Flush();
+}
+
 bool Debugger::HasIOHandlerThread() { return m_io_handler_thread.IsJoinable(); }
 
 bool Debugger::StartIOHandlerThread() {

diff  --git a/lldb/source/Symbol/LocateSymbolFile.cpp b/lldb/source/Symbol/LocateSymbolFile.cpp
index 4a7fbaae401a4..589908e4c0dc0 100644
--- a/lldb/source/Symbol/LocateSymbolFile.cpp
+++ b/lldb/source/Symbol/LocateSymbolFile.cpp
@@ -10,6 +10,7 @@
 
 #include "lldb/Core/ModuleList.h"
 #include "lldb/Core/ModuleSpec.h"
+#include "lldb/Core/Progress.h"
 #include "lldb/Host/FileSystem.h"
 #include "lldb/Symbol/ObjectFile.h"
 #include "lldb/Utility/ArchSpec.h"
@@ -262,6 +263,10 @@ Symbols::LocateExecutableSymbolFile(const ModuleSpec &module_spec,
       FileSystem::Instance().Exists(symbol_file_spec))
     return symbol_file_spec;
 
+  Progress progress(llvm::formatv(
+      "Locating external symbol file for {0}",
+      module_spec.GetFileSpec().GetFilename().AsCString("<Unknown>")));
+
   FileSpecList debug_file_search_paths = default_search_paths;
 
   // Add module directory.


        


More information about the lldb-commits mailing list