Author: Jonas Devlieghere Date: 2026-06-06T09:26:32-07:00 New Revision: 9aef31502094e2b5c997683a6d624aaf39f5bd50
URL: https://github.com/llvm/llvm-project/commit/9aef31502094e2b5c997683a6d624aaf39f5bd50 DIFF: https://github.com/llvm/llvm-project/commit/9aef31502094e2b5c997683a6d624aaf39f5bd50.diff LOG: [lldb] Add SBDebugger::SetTerminalDimensions to set width and height atomically (#201965) Terminal width and height were communicated to the debugger separately, via SetTerminalWidth() and SetTerminalHeight(). Each notified the IOHandler and the statusline, so on a resize they recomputed their layout twice: once with one dimension updated and the other still stale. Add Debugger::SetTerminalDimensions(width, height) (exposed through SBDebugger) that updates both properties before notifying, and reimplement the single-axis setters and the driver's resize handler in terms of it. Also fix SBDebugger::GetTerminalHeight(), which returned the width. Added: Modified: lldb/include/lldb/API/SBDebugger.h lldb/include/lldb/Core/Debugger.h lldb/source/API/SBDebugger.cpp lldb/source/Core/Debugger.cpp lldb/test/API/python_api/debugger/TestDebuggerAPI.py lldb/tools/driver/Driver.cpp Removed: ################################################################################ diff --git a/lldb/include/lldb/API/SBDebugger.h b/lldb/include/lldb/API/SBDebugger.h index 688fc9197965c..14b8350902811 100644 --- a/lldb/include/lldb/API/SBDebugger.h +++ b/lldb/include/lldb/API/SBDebugger.h @@ -517,14 +517,22 @@ class LLDB_API SBDebugger { uint32_t GetTerminalWidth() const; /// Set the terminal width. + LLDB_DEPRECATED_FIXME("Use SetTerminalDimensions", + "SetTerminalDimensions(uint32_t, uint32_t)") void SetTerminalWidth(uint32_t term_width); /// Get the terminal height. uint32_t GetTerminalHeight() const; /// Set the terminal height. + LLDB_DEPRECATED_FIXME("Use SetTerminalDimensions", + "SetTerminalDimensions(uint32_t, uint32_t)") void SetTerminalHeight(uint32_t term_height); + /// Set the terminal width and height together. Prefer this over the + /// single-axis setters when both are known, e.g. when handling a resize. + void SetTerminalDimensions(uint32_t term_width, uint32_t term_height); + /// Get the unique ID of this debugger. lldb::user_id_t GetID(); diff --git a/lldb/include/lldb/Core/Debugger.h b/lldb/include/lldb/Core/Debugger.h index c5242b639a31b..179ef0f38d940 100644 --- a/lldb/include/lldb/Core/Debugger.h +++ b/lldb/include/lldb/Core/Debugger.h @@ -300,6 +300,10 @@ class Debugger : public std::enable_shared_from_this<Debugger>, bool SetTerminalHeight(uint64_t term_height); + /// Set the terminal width and height together, so observers are notified + /// once with both dimensions current. + bool SetTerminalDimensions(uint64_t term_width, uint64_t term_height); + llvm::StringRef GetPrompt() const; llvm::StringRef GetPromptAnsiPrefix() const; diff --git a/lldb/source/API/SBDebugger.cpp b/lldb/source/API/SBDebugger.cpp index 0f1708c26b149..c0c7f93c0b87e 100644 --- a/lldb/source/API/SBDebugger.cpp +++ b/lldb/source/API/SBDebugger.cpp @@ -1338,7 +1338,7 @@ void SBDebugger::SetTerminalWidth(uint32_t term_width) { uint32_t SBDebugger::GetTerminalHeight() const { LLDB_INSTRUMENT_VA(this); - return (m_opaque_sp ? m_opaque_sp->GetTerminalWidth() : 0); + return (m_opaque_sp ? m_opaque_sp->GetTerminalHeight() : 0); } void SBDebugger::SetTerminalHeight(uint32_t term_height) { @@ -1348,6 +1348,14 @@ void SBDebugger::SetTerminalHeight(uint32_t term_height) { m_opaque_sp->SetTerminalHeight(term_height); } +void SBDebugger::SetTerminalDimensions(uint32_t term_width, + uint32_t term_height) { + LLDB_INSTRUMENT_VA(this, term_width, term_height); + + if (m_opaque_sp) + m_opaque_sp->SetTerminalDimensions(term_width, term_height); +} + const char *SBDebugger::GetPrompt() const { LLDB_INSTRUMENT_VA(this); diff --git a/lldb/source/Core/Debugger.cpp b/lldb/source/Core/Debugger.cpp index 0f7be00aad0d3..9a75c5eb407c5 100644 --- a/lldb/source/Core/Debugger.cpp +++ b/lldb/source/Core/Debugger.cpp @@ -463,19 +463,7 @@ uint64_t Debugger::GetTerminalWidth() const { } bool Debugger::SetTerminalWidth(uint64_t term_width) { - const uint32_t idx = ePropertyTerminalWidth; - const bool success = SetPropertyAtIndex(idx, term_width); - - if (auto handler_sp = m_io_handler_stack.Top()) - handler_sp->TerminalSizeChanged(); - - { - std::lock_guard<std::mutex> guard(m_statusline_mutex); - if (m_statusline) - m_statusline->TerminalSizeChanged(); - } - - return success; + return SetTerminalDimensions(term_width, GetTerminalHeight()); } uint64_t Debugger::GetTerminalHeight() const { @@ -485,8 +473,17 @@ uint64_t Debugger::GetTerminalHeight() const { } bool Debugger::SetTerminalHeight(uint64_t term_height) { - const uint32_t idx = ePropertyTerminalHeight; - const bool success = SetPropertyAtIndex(idx, term_height); + return SetTerminalDimensions(GetTerminalWidth(), term_height); +} + +bool Debugger::SetTerminalDimensions(uint64_t term_width, + uint64_t term_height) { + // Set both properties before notifying, so observers never recompute from a + // mix of fresh and stale dimensions. + const bool width_success = + SetPropertyAtIndex(ePropertyTerminalWidth, term_width); + const bool height_success = + SetPropertyAtIndex(ePropertyTerminalHeight, term_height); if (auto handler_sp = m_io_handler_stack.Top()) handler_sp->TerminalSizeChanged(); @@ -497,7 +494,7 @@ bool Debugger::SetTerminalHeight(uint64_t term_height) { m_statusline->TerminalSizeChanged(); } - return success; + return width_success && height_success; } bool Debugger::GetUseExternalEditor() const { diff --git a/lldb/test/API/python_api/debugger/TestDebuggerAPI.py b/lldb/test/API/python_api/debugger/TestDebuggerAPI.py index 488878b0436cd..f5c9c007d407b 100644 --- a/lldb/test/API/python_api/debugger/TestDebuggerAPI.py +++ b/lldb/test/API/python_api/debugger/TestDebuggerAPI.py @@ -42,6 +42,25 @@ def test_debugger_delete_invalid_target(self): self.assertFalse(target.IsValid()) self.dbg.DeleteTarget(target) + def test_terminal_dimensions(self): + """Test the SBDebugger terminal width/height accessors and the combined + SetTerminalDimensions() setter.""" + # SetTerminalDimensions updates both axes at once. + self.dbg.SetTerminalDimensions(143, 47) + self.assertEqual(self.dbg.GetTerminalWidth(), 143) + # Regression test: GetTerminalHeight() used to return the width. + self.assertEqual(self.dbg.GetTerminalHeight(), 47) + + # The single-axis setters change only their own dimension and leave the + # other one intact (they are implemented in terms of the combined call). + self.dbg.SetTerminalWidth(99) + self.assertEqual(self.dbg.GetTerminalWidth(), 99) + self.assertEqual(self.dbg.GetTerminalHeight(), 47) + + self.dbg.SetTerminalHeight(31) + self.assertEqual(self.dbg.GetTerminalWidth(), 99) + self.assertEqual(self.dbg.GetTerminalHeight(), 31) + def test_debugger_internal_variables(self): """Ensure that SBDebugger reachs the same instance of properties regardless CommandInterpreter's context initialization""" diff --git a/lldb/tools/driver/Driver.cpp b/lldb/tools/driver/Driver.cpp index 2bb77d275138e..a66552e0428bf 100644 --- a/lldb/tools/driver/Driver.cpp +++ b/lldb/tools/driver/Driver.cpp @@ -648,12 +648,15 @@ void Driver::UpdateWindowSize() { struct winsize window_size; if ((isatty(STDIN_FILENO) != 0) && ::ioctl(STDIN_FILENO, TIOCGWINSZ, &window_size) == 0) { - if (window_size.ws_col > 0) - m_debugger.SetTerminalWidth(window_size.ws_col); + if (window_size.ws_col > 0) { + // Set both dimensions together to avoid recomputing from a stale value. #ifndef _WIN32 - if (window_size.ws_row > 0) - m_debugger.SetTerminalHeight(window_size.ws_row); + m_debugger.SetTerminalDimensions(window_size.ws_col, window_size.ws_row); +#else + m_debugger.SetTerminalDimensions(window_size.ws_col, + m_debugger.GetTerminalHeight()); #endif + } } } _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
