OmarEmaraDev updated this revision to Diff 351547.
OmarEmaraDev added a comment.
- Handle review
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D100243/new/
https://reviews.llvm.org/D100243
Files:
lldb/source/Core/IOHandlerCursesGUI.cpp
lldb/test/API/commands/gui/expand-threads-tree/Makefile
lldb/test/API/commands/gui/expand-threads-tree/TestGuiExpandThreadsTree.py
lldb/test/API/commands/gui/expand-threads-tree/main.c
Index: lldb/test/API/commands/gui/expand-threads-tree/main.c
===================================================================
--- /dev/null
+++ lldb/test/API/commands/gui/expand-threads-tree/main.c
@@ -0,0 +1,10 @@
+#include <pthread.h>
+
+void *thread_start_routine(void *arg) { return NULL; }
+
+int main() {
+ pthread_t thread;
+ pthread_create(&thread, NULL, thread_start_routine, NULL);
+ pthread_join(thread, NULL);
+ return 0;
+}
Index: lldb/test/API/commands/gui/expand-threads-tree/TestGuiExpandThreadsTree.py
===================================================================
--- /dev/null
+++ lldb/test/API/commands/gui/expand-threads-tree/TestGuiExpandThreadsTree.py
@@ -0,0 +1,55 @@
+"""
+Test the 'gui' default thread tree expansion.
+The root process tree item and the tree item corresponding to the selected
+thread should be expanded by default.
+"""
+
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test.lldbpexpect import PExpectTest
+
+class TestGuiExpandThreadsTree(PExpectTest):
+
+ mydir = TestBase.compute_mydir(__file__)
+
+ # PExpect uses many timeouts internally and doesn't play well
+ # under ASAN on a loaded machine..
+ @skipIfAsan
+ @skipIfCursesSupportMissing
+ def test_gui(self):
+ self.build()
+
+ self.launch(executable=self.getBuildArtifact("a.out"), dimensions=(100,500))
+ self.expect("breakpoint set -r thread_start_routine", substrs=["Breakpoint 1", "address ="])
+ self.expect("run", substrs=["stop reason ="])
+
+ escape_key = chr(27).encode()
+
+ # Start the GUI and close the welcome window.
+ self.child.sendline("gui")
+ self.child.send(escape_key)
+ self.child.expect_exact("Threads")
+
+ # The thread running thread_start_routine should be expanded.
+ self.child.expect_exact("frame #0: thread_start_routine")
+
+ # Exit GUI.
+ self.child.send(escape_key)
+ self.expect_prompt()
+
+ # Select the main thread.
+ self.child.sendline("thread select 1")
+
+ # Start the GUI.
+ self.child.sendline("gui")
+ self.child.expect_exact("Threads")
+
+ # The main thread should be expanded.
+ self.child.expect("frame #\d+: main")
+
+ # Quit the GUI
+ self.child.send(escape_key)
+
+ self.expect_prompt()
+ self.quit()
Index: lldb/test/API/commands/gui/expand-threads-tree/Makefile
===================================================================
--- /dev/null
+++ lldb/test/API/commands/gui/expand-threads-tree/Makefile
@@ -0,0 +1,3 @@
+C_SOURCES := main.c
+ENABLE_THREADS := YES
+include Makefile.rules
Index: lldb/source/Core/IOHandlerCursesGUI.cpp
===================================================================
--- lldb/source/Core/IOHandlerCursesGUI.cpp
+++ lldb/source/Core/IOHandlerCursesGUI.cpp
@@ -1608,8 +1608,13 @@
virtual void TreeDelegateDrawTreeItem(TreeItem &item, Window &window) = 0;
virtual void TreeDelegateGenerateChildren(TreeItem &item) = 0;
+ virtual void TreeDelegateUpdateSelection(TreeItem &root, int &selection_index,
+ TreeItem *&selected_item) {
+ return;
+ }
virtual bool TreeDelegateItemSelected(
TreeItem &item) = 0; // Return true if we need to update views
+ virtual bool TreeDelegateExpandRootByDefault() { return false; }
};
typedef std::shared_ptr<TreeDelegate> TreeDelegateSP;
@@ -1619,7 +1624,10 @@
TreeItem(TreeItem *parent, TreeDelegate &delegate, bool might_have_children)
: m_parent(parent), m_delegate(delegate), m_user_data(nullptr),
m_identifier(0), m_row_idx(-1), m_children(),
- m_might_have_children(might_have_children), m_is_expanded(false) {}
+ m_might_have_children(might_have_children), m_is_expanded(false) {
+ if (m_parent == nullptr)
+ m_is_expanded = m_delegate.TreeDelegateExpandRootByDefault();
+ }
TreeItem &operator=(const TreeItem &rhs) {
if (this != &rhs) {
@@ -1848,6 +1856,8 @@
const int num_visible_rows = NumVisibleRows();
m_num_rows = 0;
m_root.CalculateRowIndexes(m_num_rows);
+ m_delegate_sp->TreeDelegateUpdateSelection(m_root, m_selected_row_idx,
+ m_selected_item);
// If we unexpanded while having something selected our total number of
// rows is less than the num visible rows, then make sure we show all the
@@ -2149,7 +2159,7 @@
public:
ThreadsTreeDelegate(Debugger &debugger)
: TreeDelegate(), m_thread_delegate_sp(), m_debugger(debugger),
- m_stop_id(UINT32_MAX) {
+ m_stop_id(UINT32_MAX), m_update_selection(false) {
FormatEntity::Parse("process ${process.id}{, name = ${process.name}}",
m_format);
}
@@ -2177,6 +2187,7 @@
void TreeDelegateGenerateChildren(TreeItem &item) override {
ProcessSP process_sp = GetProcess();
+ m_update_selection = false;
if (process_sp && process_sp->IsAlive()) {
StateType state = process_sp->GetState();
if (StateIsStoppedState(state, true)) {
@@ -2185,6 +2196,7 @@
return; // Children are already up to date
m_stop_id = stop_id;
+ m_update_selection = true;
if (!m_thread_delegate_sp) {
// Always expand the thread item the first time we show it
@@ -2196,11 +2208,15 @@
TreeItem t(&item, *m_thread_delegate_sp, false);
ThreadList &threads = process_sp->GetThreadList();
std::lock_guard<std::recursive_mutex> guard(threads.GetMutex());
+ ThreadSP selected_thread = threads.GetSelectedThread();
size_t num_threads = threads.GetSize();
item.Resize(num_threads, t);
for (size_t i = 0; i < num_threads; ++i) {
- item[i].SetIdentifier(threads.GetThreadAtIndex(i)->GetID());
+ ThreadSP thread = threads.GetThreadAtIndex(i);
+ item[i].SetIdentifier(thread->GetID());
item[i].SetMightHaveChildren(true);
+ if (selected_thread->GetID() == thread->GetID())
+ item[i].Expand();
}
return;
}
@@ -2208,12 +2224,42 @@
item.ClearChildren();
}
+ void TreeDelegateUpdateSelection(TreeItem &root, int &selection_index,
+ TreeItem *&selected_item) override {
+ if (!m_update_selection)
+ return;
+
+ ProcessSP process_sp = GetProcess();
+ if (!(process_sp && process_sp->IsAlive()))
+ return;
+
+ StateType state = process_sp->GetState();
+ if (!StateIsStoppedState(state, true))
+ return;
+
+ ThreadList &threads = process_sp->GetThreadList();
+ std::lock_guard<std::recursive_mutex> guard(threads.GetMutex());
+ ThreadSP selected_thread = threads.GetSelectedThread();
+ size_t num_threads = threads.GetSize();
+ for (size_t i = 0; i < num_threads; ++i) {
+ ThreadSP thread = threads.GetThreadAtIndex(i);
+ if (selected_thread->GetID() == thread->GetID()) {
+ selected_item = &root[i][thread->GetSelectedFrameIndex()];
+ selection_index = selected_item->GetRowIndex();
+ return;
+ }
+ }
+ }
+
bool TreeDelegateItemSelected(TreeItem &item) override { return false; }
+ bool TreeDelegateExpandRootByDefault() override { return true; }
+
protected:
std::shared_ptr<ThreadTreeDelegate> m_thread_delegate_sp;
Debugger &m_debugger;
uint32_t m_stop_id;
+ bool m_update_selection;
FormatEntity::Entry m_format;
};
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits