[LLDB] Add SBProgress so Python scripts can also report progress (#119052)
Recently I've been working on a lot of internal Python tooling, and in certain cases I want to report async to the script over DAP. Progress.h already handles this, so I've exposed Progress via the SB API so Python scripts can also update progress objects. I actually have no idea how to test this, so I just wrote a [toy command to test it](https://gist.github.com/Jlalond/48d85e75a91f7a137e3142e6a13d0947)  I also copied the first section of the extensive Progress.h class documentation to the docstrings.
This commit is contained in:
@@ -52,6 +52,7 @@
|
||||
#include "lldb/API/SBProcess.h"
|
||||
#include "lldb/API/SBProcessInfo.h"
|
||||
#include "lldb/API/SBProcessInfoList.h"
|
||||
#include "lldb/API/SBProgress.h"
|
||||
#include "lldb/API/SBQueue.h"
|
||||
#include "lldb/API/SBQueueItem.h"
|
||||
#include "lldb/API/SBReproducer.h"
|
||||
|
||||
14
lldb/bindings/interface/SBProgressDocstrings.i
Normal file
14
lldb/bindings/interface/SBProgressDocstrings.i
Normal file
@@ -0,0 +1,14 @@
|
||||
%feature("docstring",
|
||||
"A Progress indicator helper class.
|
||||
|
||||
Any potentially long running sections of code in LLDB should report
|
||||
progress so that clients are aware of delays that might appear during
|
||||
debugging. Delays commonly include indexing debug information, parsing
|
||||
symbol tables for object files, downloading symbols from remote
|
||||
repositories, and many more things.
|
||||
|
||||
The Progress class helps make sure that progress is correctly reported
|
||||
and will always send an initial progress update, updates when
|
||||
Progress::Increment() is called, and also will make sure that a progress
|
||||
completed update is reported even if the user doesn't explicitly cause one
|
||||
to be sent.") lldb::SBProgress;
|
||||
@@ -54,6 +54,7 @@
|
||||
%include "./interface/SBPlatformDocstrings.i"
|
||||
%include "./interface/SBProcessDocstrings.i"
|
||||
%include "./interface/SBProcessInfoDocstrings.i"
|
||||
%include "./interface/SBProgressDocstrings.i"
|
||||
%include "./interface/SBQueueDocstrings.i"
|
||||
%include "./interface/SBQueueItemDocstrings.i"
|
||||
%include "./interface/SBReproducerDocstrings.i"
|
||||
@@ -133,6 +134,7 @@
|
||||
%include "lldb/API/SBProcess.h"
|
||||
%include "lldb/API/SBProcessInfo.h"
|
||||
%include "lldb/API/SBProcessInfoList.h"
|
||||
%include "lldb/API/SBProgress.h"
|
||||
%include "lldb/API/SBQueue.h"
|
||||
%include "lldb/API/SBQueueItem.h"
|
||||
%include "lldb/API/SBReproducer.h"
|
||||
|
||||
@@ -203,7 +203,7 @@ public:
|
||||
lldb::SBCommandInterpreter GetCommandInterpreter();
|
||||
|
||||
void HandleCommand(const char *command);
|
||||
|
||||
|
||||
void RequestInterrupt();
|
||||
void CancelInterruptRequest();
|
||||
bool InterruptRequested();
|
||||
@@ -517,6 +517,7 @@ private:
|
||||
friend class SBPlatform;
|
||||
friend class SBTarget;
|
||||
friend class SBTrace;
|
||||
friend class SBProgress;
|
||||
|
||||
lldb::SBTarget FindTargetWithLLDBProcess(const lldb::ProcessSP &processSP);
|
||||
|
||||
|
||||
66
lldb/include/lldb/API/SBProgress.h
Normal file
66
lldb/include/lldb/API/SBProgress.h
Normal file
@@ -0,0 +1,66 @@
|
||||
//===-- SBProgress.h --------------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLDB_API_SBPROGRESS_H
|
||||
#define LLDB_API_SBPROGRESS_H
|
||||
|
||||
#include "lldb/API/SBDebugger.h"
|
||||
#include "lldb/API/SBDefines.h"
|
||||
|
||||
namespace lldb {
|
||||
|
||||
/// A Progress indicator helper class.
|
||||
///
|
||||
/// Any potentially long running sections of code in LLDB should report
|
||||
/// progress so that clients are aware of delays that might appear during
|
||||
/// debugging. Delays commonly include indexing debug information, parsing
|
||||
/// symbol tables for object files, downloading symbols from remote
|
||||
/// repositories, and many more things.
|
||||
///
|
||||
/// The Progress class helps make sure that progress is correctly reported
|
||||
/// and will always send an initial progress update, updates when
|
||||
/// Progress::Increment() is called, and also will make sure that a progress
|
||||
/// completed update is reported even if the user doesn't explicitly cause one
|
||||
/// to be sent.
|
||||
class LLDB_API SBProgress {
|
||||
public:
|
||||
/// Construct a progress object with a title, details and a given debugger.
|
||||
/// \param title
|
||||
/// The title of the progress object.
|
||||
/// \param details
|
||||
/// The details of the progress object.
|
||||
/// \param debugger
|
||||
/// The debugger for this progress object to report to.
|
||||
SBProgress(const char *title, const char *details, SBDebugger &debugger);
|
||||
|
||||
/// Construct a progress object with a title, details, the total units of work
|
||||
/// to be done, and a given debugger.
|
||||
/// \param title
|
||||
/// The title of the progress object.
|
||||
/// \param details
|
||||
/// The details of the progress object.
|
||||
/// \param total_units
|
||||
/// The total number of units of work to be done.
|
||||
/// \param debugger
|
||||
/// The debugger for this progress object to report to.
|
||||
SBProgress(const char *title, const char *details, uint64_t total_units,
|
||||
SBDebugger &debugger);
|
||||
|
||||
~SBProgress();
|
||||
|
||||
void Increment(uint64_t amount, const char *description = nullptr);
|
||||
|
||||
protected:
|
||||
lldb_private::Progress &ref() const;
|
||||
|
||||
private:
|
||||
std::unique_ptr<lldb_private::Progress> m_opaque_up;
|
||||
}; // SBProgress
|
||||
} // namespace lldb
|
||||
|
||||
#endif // LLDB_API_SBPROGRESS_H
|
||||
@@ -233,6 +233,7 @@ class Symtab;
|
||||
class SyntheticChildren;
|
||||
class SyntheticChildrenFrontEnd;
|
||||
class SystemRuntime;
|
||||
class Progress;
|
||||
class Target;
|
||||
class TargetList;
|
||||
class TargetProperties;
|
||||
|
||||
@@ -83,6 +83,7 @@ add_lldb_library(liblldb SHARED ${option_framework}
|
||||
SBModule.cpp
|
||||
SBModuleSpec.cpp
|
||||
SBPlatform.cpp
|
||||
SBProgress.cpp
|
||||
SBProcess.cpp
|
||||
SBProcessInfo.cpp
|
||||
SBProcessInfoList.cpp
|
||||
|
||||
43
lldb/source/API/SBProgress.cpp
Normal file
43
lldb/source/API/SBProgress.cpp
Normal file
@@ -0,0 +1,43 @@
|
||||
//===-- SBProgress.cpp --------------------------------------------------*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "lldb/API/SBProgress.h"
|
||||
#include "lldb/Core/Progress.h"
|
||||
#include "lldb/Utility/Instrumentation.h"
|
||||
|
||||
using namespace lldb;
|
||||
|
||||
SBProgress::SBProgress(const char *title, const char *details,
|
||||
SBDebugger &debugger) {
|
||||
LLDB_INSTRUMENT_VA(this, title, details, debugger);
|
||||
|
||||
m_opaque_up = std::make_unique<lldb_private::Progress>(
|
||||
title, details, /*total=*/std::nullopt, debugger.get(),
|
||||
/*minimum_report_time=*/std::nullopt,
|
||||
lldb_private::Progress::Origin::eExternal);
|
||||
}
|
||||
|
||||
SBProgress::SBProgress(const char *title, const char *details,
|
||||
uint64_t total_units, SBDebugger &debugger) {
|
||||
LLDB_INSTRUMENT_VA(this, title, details, total_units, debugger);
|
||||
|
||||
m_opaque_up = std::make_unique<lldb_private::Progress>(
|
||||
title, details, total_units, debugger.get(),
|
||||
/*minimum_report_time=*/std::nullopt,
|
||||
lldb_private::Progress::Origin::eExternal);
|
||||
}
|
||||
|
||||
SBProgress::~SBProgress() = default;
|
||||
|
||||
void SBProgress::Increment(uint64_t amount, const char *description) {
|
||||
LLDB_INSTRUMENT_VA(amount, description);
|
||||
|
||||
m_opaque_up->Increment(amount, description);
|
||||
}
|
||||
|
||||
lldb_private::Progress &SBProgress::ref() const { return *m_opaque_up; }
|
||||
@@ -1952,7 +1952,8 @@ lldb::thread_result_t Debugger::DefaultEventHandler() {
|
||||
listener_sp->StartListeningForEvents(
|
||||
&m_broadcaster, lldb::eBroadcastBitProgress | lldb::eBroadcastBitWarning |
|
||||
lldb::eBroadcastBitError |
|
||||
lldb::eBroadcastSymbolChange);
|
||||
lldb::eBroadcastSymbolChange |
|
||||
lldb::eBroadcastBitExternalProgress);
|
||||
|
||||
// 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
|
||||
|
||||
35
lldb/test/API/python_api/sbprogress/TestSBProgress.py
Normal file
35
lldb/test/API/python_api/sbprogress/TestSBProgress.py
Normal file
@@ -0,0 +1,35 @@
|
||||
"""Test the SBProgress API."""
|
||||
|
||||
import lldb
|
||||
from lldbsuite.test.lldbtest import *
|
||||
|
||||
|
||||
class SBProgressTestCase(TestBase):
|
||||
def test_with_external_bit_set(self):
|
||||
"""Test SBProgress events are listened to when the external bit is set."""
|
||||
|
||||
progress = lldb.SBProgress("Test SBProgress", "Test progress", self.dbg)
|
||||
listener = lldb.SBListener("Test listener")
|
||||
broadcaster = self.dbg.GetBroadcaster()
|
||||
broadcaster.AddListener(listener, lldb.eBroadcastBitExternalProgress)
|
||||
event = lldb.SBEvent()
|
||||
|
||||
expected_string = "Test progress first increment"
|
||||
progress.Increment(1, expected_string)
|
||||
self.assertTrue(listener.PeekAtNextEvent(event))
|
||||
stream = lldb.SBStream()
|
||||
event.GetDescription(stream)
|
||||
self.assertIn(expected_string, stream.GetData())
|
||||
|
||||
def test_without_external_bit_set(self):
|
||||
"""Test SBProgress events are not listened to on the internal progress bit."""
|
||||
|
||||
progress = lldb.SBProgress("Test SBProgress", "Test progress", self.dbg)
|
||||
listener = lldb.SBListener("Test listener")
|
||||
broadcaster = self.dbg.GetBroadcaster()
|
||||
broadcaster.AddListener(listener, lldb.eBroadcastBitProgress)
|
||||
event = lldb.SBEvent()
|
||||
|
||||
expected_string = "Test progress first increment"
|
||||
progress.Increment(1, expected_string)
|
||||
self.assertFalse(listener.PeekAtNextEvent(event))
|
||||
Reference in New Issue
Block a user