Index: lldb/include/lldb/Core/Debugger.h =================================================================== --- lldb/include/lldb/Core/Debugger.h +++ lldb/include/lldb/Core/Debugger.h @@ -479,7 +479,7 @@ // It needs to get constructed before the target_list or any other member // that might want to broadcast through the debugger. - TerminalState m_terminal_state; + Terminal m_terminal; TargetList m_target_list; PlatformList m_platform_list; Index: lldb/include/lldb/Host/Terminal.h =================================================================== --- lldb/include/lldb/Host/Terminal.h +++ lldb/include/lldb/Host/Terminal.h @@ -13,10 +13,18 @@ #include "lldb/Host/Config.h" #include "lldb/lldb-private.h" -struct termios; +#if LLDB_ENABLE_TERMIOS +#include +#endif namespace lldb_private { +/// \class Terminal Terminal.h "lldb/Host/Terminal.h" +/// A terminal wrapper with state saving support. +/// +/// This class provides a portable wrapper for low-level terminal properties. +/// It can also be used to store the initial terminal state and restore it +/// later. class Terminal { public: Terminal(int fd = -1) : m_fd(fd) {} @@ -27,60 +35,42 @@ int GetFileDescriptor() const { return m_fd; } - void SetFileDescriptor(int fd) { m_fd = fd; } + void SetFileDescriptor(int fd) { + m_fd = fd; + ClearSavedState(); + } bool FileDescriptorIsValid() const { return m_fd != -1; } - void Clear() { m_fd = -1; } + void Clear() { SetFileDescriptor(-1); } bool SetEcho(bool enabled); bool SetCanonical(bool enabled); -protected: - int m_fd; // This may or may not be a terminal file descriptor -}; - -/// \class State Terminal.h "lldb/Host/Terminal.h" -/// A terminal state saving/restoring class. -/// -/// This class can be used to remember the terminal state for a file -/// descriptor and later restore that state as it originally was. -class TerminalState { -public: - /// Default constructor - TerminalState(); - - /// Destructor - ~TerminalState(); - - /// Save the TTY state for \a fd. - /// - /// Save the current state of the TTY for the file descriptor "fd" and if - /// "save_process_group" is true, attempt to save the process group info for - /// the TTY. + /// Save the TTY state for the terminal. /// - /// \param[in] fd - /// The file descriptor to save the state of. + /// Save the current state of the current TTY and if "save_process_group" + /// is true, attempt to save the process group info for the TTY. /// /// \param[in] save_process_group /// If \b true, save the process group settings, else do not /// save the process group settings for a TTY. /// /// \return - /// Returns \b true if \a fd describes a TTY and if the state + /// Returns \b true if the fd describes a TTY and if the state /// was able to be saved, \b false otherwise. - bool Save(int fd, bool save_process_group); + bool SaveState(bool save_process_group); /// Restore the TTY state to the cached state. /// /// Restore the state of the TTY using the cached values from a previous - /// call to TerminalState::Save(int,bool). + /// call to TerminalState::SaveState(bool). /// /// \return /// Returns \b true if the TTY state was successfully restored, /// \b false otherwise. - bool Restore() const; + bool RestoreState() const; /// Test for valid cached TTY state information. /// @@ -88,9 +78,9 @@ /// Returns \b true if this object has valid saved TTY state /// settings that can be used to restore a previous state, /// \b false otherwise. - bool IsValid() const; + bool IsStateValid() const; - void Clear(); + void ClearSavedState(); protected: /// Test if tflags is valid. @@ -115,7 +105,7 @@ bool ProcessGroupIsValid() const; // Member variables - Terminal m_tty; ///< A terminal + int m_fd; ///< Current file descriptor int m_tflags = -1; ///< Cached tflags information. #if LLDB_ENABLE_TERMIOS std::unique_ptr Index: lldb/source/Core/Debugger.cpp =================================================================== --- lldb/source/Core/Debugger.cpp +++ lldb/source/Core/Debugger.cpp @@ -686,7 +686,7 @@ m_error_stream_sp(std::make_shared(stderr, false)), m_input_recorder(nullptr), m_broadcaster_manager_sp(BroadcasterManager::MakeBroadcasterManager()), - m_terminal_state(), m_target_list(*this), m_platform_list(), + m_terminal(), m_target_list(*this), m_platform_list(), m_listener_sp(Listener::MakeListener("lldb.Debugger")), m_source_manager_up(), m_source_file_cache(), m_command_interpreter_up( @@ -784,7 +784,7 @@ // Close the input file _before_ we close the input read communications // class as it does NOT own the input file, our m_input_file does. - m_terminal_state.Clear(); + m_terminal.Clear(); GetInputFile().Close(); m_command_interpreter_up->Clear(); @@ -831,11 +831,13 @@ void Debugger::SaveInputTerminalState() { int fd = GetInputFile().GetDescriptor(); - if (fd != File::kInvalidDescriptor) - m_terminal_state.Save(fd, true); + if (fd != File::kInvalidDescriptor) { + m_terminal.SetFileDescriptor(fd); + m_terminal.SaveState(true); + } } -void Debugger::RestoreInputTerminalState() { m_terminal_state.Restore(); } +void Debugger::RestoreInputTerminalState() { m_terminal.RestoreState(); } ExecutionContext Debugger::GetSelectedExecutionContext() { bool adopt_selected = true; Index: lldb/source/Host/common/Terminal.cpp =================================================================== --- lldb/source/Host/common/Terminal.cpp +++ lldb/source/Host/common/Terminal.cpp @@ -81,21 +81,7 @@ return false; } -// Default constructor -TerminalState::TerminalState() - : m_tty() -#if LLDB_ENABLE_TERMIOS - , - m_termios_up() -#endif -{ -} - -// Destructor -TerminalState::~TerminalState() = default; - -void TerminalState::Clear() { - m_tty.Clear(); +void Terminal::ClearSavedState() { m_tflags = -1; #if LLDB_ENABLE_TERMIOS m_termios_up.reset(); @@ -103,51 +89,43 @@ m_process_group = -1; } -// Save the current state of the TTY for the file descriptor "fd" and if -// "save_process_group" is true, attempt to save the process group info for the -// TTY. -bool TerminalState::Save(int fd, bool save_process_group) { - m_tty.SetFileDescriptor(fd); - if (m_tty.IsATerminal()) { +bool Terminal::SaveState(bool save_process_group) { + if (IsATerminal()) { #if LLDB_ENABLE_POSIX - m_tflags = ::fcntl(fd, F_GETFL, 0); + m_tflags = ::fcntl(m_fd, F_GETFL, 0); #endif #if LLDB_ENABLE_TERMIOS if (m_termios_up == nullptr) m_termios_up.reset(new struct termios); - int err = ::tcgetattr(fd, m_termios_up.get()); + int err = ::tcgetattr(m_fd, m_termios_up.get()); if (err != 0) m_termios_up.reset(); #endif // #if LLDB_ENABLE_TERMIOS #if LLDB_ENABLE_POSIX if (save_process_group) - m_process_group = ::tcgetpgrp(0); + m_process_group = ::tcgetpgrp(m_fd); else m_process_group = -1; #endif } else { - m_tty.Clear(); m_tflags = -1; #if LLDB_ENABLE_TERMIOS m_termios_up.reset(); #endif m_process_group = -1; } - return IsValid(); + return IsStateValid(); } -// Restore the state of the TTY using the cached values from a previous call to -// Save(). -bool TerminalState::Restore() const { +bool Terminal::RestoreState() const { #if LLDB_ENABLE_POSIX - if (IsValid()) { - const int fd = m_tty.GetFileDescriptor(); + if (IsStateValid()) { if (TFlagsIsValid()) - fcntl(fd, F_SETFL, m_tflags); + fcntl(m_fd, F_SETFL, m_tflags); #if LLDB_ENABLE_TERMIOS if (TTYStateIsValid()) - tcsetattr(fd, TCSANOW, m_termios_up.get()); + tcsetattr(m_fd, TCSANOW, m_termios_up.get()); #endif // #if LLDB_ENABLE_TERMIOS if (ProcessGroupIsValid()) { @@ -155,7 +133,7 @@ void (*saved_sigttou_callback)(int) = nullptr; saved_sigttou_callback = (void (*)(int))signal(SIGTTOU, SIG_IGN); // Set the process group - tcsetpgrp(fd, m_process_group); + tcsetpgrp(m_fd, m_process_group); // Restore the original signal handler. signal(SIGTTOU, saved_sigttou_callback); } @@ -165,18 +143,13 @@ return false; } -// Returns true if this object has valid saved TTY state settings that can be -// used to restore a previous state. -bool TerminalState::IsValid() const { - return m_tty.FileDescriptorIsValid() && - (TFlagsIsValid() || TTYStateIsValid()); +bool Terminal::IsStateValid() const { + return FileDescriptorIsValid() && (TFlagsIsValid() || TTYStateIsValid()); } -// Returns true if m_tflags is valid -bool TerminalState::TFlagsIsValid() const { return m_tflags != -1; } +bool Terminal::TFlagsIsValid() const { return m_tflags != -1; } -// Returns true if m_ttystate is valid -bool TerminalState::TTYStateIsValid() const { +bool Terminal::TTYStateIsValid() const { #if LLDB_ENABLE_TERMIOS return m_termios_up != nullptr; #else @@ -184,7 +157,6 @@ #endif } -// Returns true if m_process_group is valid -bool TerminalState::ProcessGroupIsValid() const { +bool Terminal::ProcessGroupIsValid() const { return static_cast(m_process_group) != -1; } Index: lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp =================================================================== --- lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp +++ lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp @@ -355,7 +355,6 @@ PyEval_InitThreads(); } - TerminalState m_stdin_tty_state; PyGILState_STATE m_gil_state = PyGILState_UNLOCKED; bool m_was_already_initialized = false; }; Index: lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h =================================================================== --- lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h +++ lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h @@ -430,11 +430,10 @@ int stdin_fd = GetInputFD(); if (stdin_fd >= 0) { Terminal terminal(stdin_fd); - TerminalState terminal_state; const bool is_a_tty = terminal.IsATerminal(); if (is_a_tty) { - terminal_state.Save(stdin_fd, false); + terminal.SaveState(false); terminal.SetCanonical(false); terminal.SetEcho(true); } @@ -466,7 +465,7 @@ PyRun_SimpleString(run_string.GetData()); if (is_a_tty) - terminal_state.Restore(); + terminal.RestoreState(); } } SetIsDone(true); Index: lldb/source/Target/Process.cpp =================================================================== --- lldb/source/Target/Process.cpp +++ lldb/source/Target/Process.cpp @@ -4351,9 +4351,8 @@ SetIsDone(false); const int read_fd = m_read_file.GetDescriptor(); - TerminalState terminal_state; - terminal_state.Save(read_fd, false); Terminal terminal(read_fd); + terminal.SaveState(false); terminal.SetCanonical(false); terminal.SetEcho(false); // FD_ZERO, FD_SET are not supported on windows @@ -4399,7 +4398,7 @@ } m_is_running = false; #endif - terminal_state.Restore(); + terminal.RestoreState(); } void Cancel() override {