From c5917d9a38ce0e4ad0a8f888f759de382dbe8f2d Mon Sep 17 00:00:00 2001 From: Jim Ingham Date: Fri, 30 Nov 2012 20:23:19 +0000 Subject: [PATCH] Save and restore terminal state when lldb is suspended with SIGTSTP and resumed with SIGCONT. Readline & gdb have a bunch of code to handle older UNIX'es with other job control mechanisms. I didn't try to replicate that. llvm-svn: 169032 --- lldb/include/lldb/API/SBDebugger.h | 8 +++++++- lldb/include/lldb/Core/Debugger.h | 7 +++++++ lldb/include/lldb/Host/Terminal.h | 3 +++ lldb/source/API/SBDebugger.cpp | 14 ++++++++++++++ lldb/source/Core/Debugger.cpp | 21 ++++++++++++++++++++- lldb/source/Host/common/Terminal.cpp | 9 +++++++++ lldb/tools/driver/Driver.cpp | 20 ++++++++++++++++++++ 7 files changed, 80 insertions(+), 2 deletions(-) diff --git a/lldb/include/lldb/API/SBDebugger.h b/lldb/include/lldb/API/SBDebugger.h index 41bcfa5..2de86d6 100644 --- a/lldb/include/lldb/API/SBDebugger.h +++ b/lldb/include/lldb/API/SBDebugger.h @@ -78,7 +78,7 @@ public: void SetErrorFileHandle (FILE *f, bool transfer_ownership); - + FILE * GetInputFileHandle (); @@ -88,6 +88,12 @@ public: FILE * GetErrorFileHandle (); + void + SaveInputTerminalState(); + + void + RestoreInputTerminalState(); + lldb::SBCommandInterpreter GetCommandInterpreter (); diff --git a/lldb/include/lldb/Core/Debugger.h b/lldb/include/lldb/Core/Debugger.h index 67fa370..f47153b 100644 --- a/lldb/include/lldb/Core/Debugger.h +++ b/lldb/include/lldb/Core/Debugger.h @@ -116,6 +116,12 @@ public: void SetErrorFileHandle (FILE *fh, bool tranfer_ownership); + + void + SaveInputTerminalState(); + + void + RestoreInputTerminalState(); Stream& GetOutputStream () @@ -351,6 +357,7 @@ protected: StreamFile m_input_file; StreamFile m_output_file; StreamFile m_error_file; + TerminalState m_terminal_state; TargetList m_target_list; PlatformList m_platform_list; Listener m_listener; diff --git a/lldb/include/lldb/Host/Terminal.h b/lldb/include/lldb/Host/Terminal.h index dfa3451..201f07a 100644 --- a/lldb/include/lldb/Host/Terminal.h +++ b/lldb/include/lldb/Host/Terminal.h @@ -132,6 +132,9 @@ public: //------------------------------------------------------------------ bool IsValid() const; + + void + Clear (); protected: diff --git a/lldb/source/API/SBDebugger.cpp b/lldb/source/API/SBDebugger.cpp index af9447a..0c957a6 100644 --- a/lldb/source/API/SBDebugger.cpp +++ b/lldb/source/API/SBDebugger.cpp @@ -291,6 +291,20 @@ SBDebugger::GetErrorFileHandle () return NULL; } +void +SBDebugger::SaveInputTerminalState() +{ + if (m_opaque_sp) + m_opaque_sp->SaveInputTerminalState(); +} + +void +SBDebugger::RestoreInputTerminalState() +{ + if (m_opaque_sp) + m_opaque_sp->RestoreInputTerminalState(); + +} SBCommandInterpreter SBDebugger::GetCommandInterpreter () { diff --git a/lldb/source/Core/Debugger.cpp b/lldb/source/Core/Debugger.cpp index aadbf4d..e817868 100644 --- a/lldb/source/Core/Debugger.cpp +++ b/lldb/source/Core/Debugger.cpp @@ -548,6 +548,7 @@ Debugger::Debugger (lldb::LogOutputCallback log_callback, void *baton) : m_input_file (), m_output_file (), m_error_file (), + m_terminal_state (), m_target_list (*this), m_platform_list (), m_listener ("lldb.Debugger"), @@ -615,6 +616,7 @@ Debugger::Clear() // 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(); GetInputFile().Close (); // Now that we have closed m_input_file, we can now tell our input communication // class to close down. Its read thread should quickly exit after we close @@ -662,7 +664,10 @@ Debugger::SetInputFileHandle (FILE *fh, bool tranfer_ownership) // want to objects trying to own and close a file descriptor. m_input_comm.SetConnection (new ConnectionFileDescriptor (in_file.GetDescriptor(), false)); m_input_comm.SetReadThreadBytesReceivedCallback (Debugger::DispatchInputCallback, this); - + + // Save away the terminal state if that is relevant, so that we can restore it in RestoreInputState. + SaveInputTerminalState (); + Error error; if (m_input_comm.StartReadThread (&error) == false) { @@ -698,6 +703,20 @@ Debugger::SetErrorFileHandle (FILE *fh, bool tranfer_ownership) err_file.SetStream (stderr, false); } +void +Debugger::SaveInputTerminalState () +{ + File &in_file = GetInputFile(); + if (in_file.GetDescriptor() != File::kInvalidDescriptor) + m_terminal_state.Save(in_file.GetDescriptor(), true); +} + +void +Debugger::RestoreInputTerminalState () +{ + m_terminal_state.Restore(); +} + ExecutionContext Debugger::GetSelectedExecutionContext () { diff --git a/lldb/source/Host/common/Terminal.cpp b/lldb/source/Host/common/Terminal.cpp index ce0e15f..89d21cf 100644 --- a/lldb/source/Host/common/Terminal.cpp +++ b/lldb/source/Host/common/Terminal.cpp @@ -120,6 +120,15 @@ TerminalState::~TerminalState() { } +void +TerminalState::Clear () +{ + m_tty.Clear(); + m_tflags = -1; + m_termios_ap.reset(); + 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 diff --git a/lldb/tools/driver/Driver.cpp b/lldb/tools/driver/Driver.cpp index 85fec51..b410f57 100644 --- a/lldb/tools/driver/Driver.cpp +++ b/lldb/tools/driver/Driver.cpp @@ -1579,6 +1579,24 @@ sigint_handler (int signo) exit (signo); } +void +sigtstp_handler (int signo) +{ + g_driver->GetDebugger().SaveInputTerminalState(); + signal (signo, SIG_DFL); + kill (getpid(), signo); + signal (signo, sigtstp_handler); +} + +void +sigcont_handler (int signo) +{ + g_driver->GetDebugger().RestoreInputTerminalState(); + signal (signo, SIG_DFL); + kill (getpid(), signo); + signal (signo, sigcont_handler); +} + int main (int argc, char const *argv[], const char *envp[]) { @@ -1589,6 +1607,8 @@ main (int argc, char const *argv[], const char *envp[]) signal (SIGPIPE, SIG_IGN); signal (SIGWINCH, sigwinch_handler); signal (SIGINT, sigint_handler); + signal (SIGTSTP, sigtstp_handler); + signal (SIGCONT, sigcont_handler); // Create a scope for driver so that the driver object will destroy itself // before SBDebugger::Terminate() is called. -- 2.7.4