[nemiver] Save and restore tty attributes



commit cbcd0ff0dc03d7a9b3c831a98efb3f1c3d8c9a34
Author: Tom Hughes <tom compton nu>
Date:   Sat Jun 23 14:00:44 2012 +0200

    Save and restore tty attributes
    
    	* src/dbgengine/nmv-i-debugger.h (IDebugger::load_program): Take
    	additional slave_tty_fd and uses_launch_tty parameters.
    	* src/dbgengine/nmv-gdb-engine.h (GDBEngine::load_program):
    	Likewise.
    	* src/dbgengine/nmv-gdb-engine.cc
    	(GDBengine::Priv::{uses_launch_tty, tt_attributes, tty_path,
    	tty_fd): New members.
    	(GDBEngine::Priv::Priv): Initialize the new members above.
    	(GDBEngine::Priv::{get_tty_attributes,set_tty_attributes}): New
    	functions.
    	(GDBEngine::Priv::issue_command): When issuing a "re-run" command
    	make sure to re-set the tty attribute to their initial state.
    	(GDBEngine::load_program): In compliance with the above change on
    	the interface of this function, Take additional slave_tty_fd and
    	uses_launch_tty parameters.  Call new m_priv->get_tty_attributes before
    	really launching GDB.  Adjust call from load_program overload.
    	Update comment.
    	(GDBEngine::exit_engine): Call new m_priv->set_tty_attributes
    	after debugger exited.  Add comment.
    	* src/uicommon/nmv-terminal.h (Terminal::slave_ptr): Declare ...
    	* src/uicommon/nmv-terminal.cc (Terminal::slave_pty): ... new
    	function.
    	* src/persp/dbgperspective/nmv-dbg-perspective.cc
    	(DBGPerspective::execute_program): Adjust call to the
    	IDebugger::load_program.
    	(DBGPerspective::on_shutdown_signal): Re-indent comment.
    	(DBGPerspective::get_terminal_name): Add comment.
    
    Signed-off-by: Dodji Seketeli <dodji seketeli org>

 src/dbgengine/nmv-gdb-engine.cc                 |   77 +++++++++++++++++++++--
 src/dbgengine/nmv-gdb-engine.h                  |    4 +-
 src/dbgengine/nmv-i-debugger.h                  |    4 +-
 src/persp/dbgperspective/nmv-dbg-perspective.cc |   16 ++++-
 src/uicommon/nmv-terminal.cc                    |   10 +++
 src/uicommon/nmv-terminal.h                     |    1 +
 6 files changed, 103 insertions(+), 9 deletions(-)
---
diff --git a/src/dbgengine/nmv-gdb-engine.cc b/src/dbgengine/nmv-gdb-engine.cc
index 8140bf5..2bb076f 100644
--- a/src/dbgengine/nmv-gdb-engine.cc
+++ b/src/dbgengine/nmv-gdb-engine.cc
@@ -222,6 +222,10 @@ public:
     OutputHandlerList output_handler_list;
     IDebugger::State state;
     bool is_running;
+    bool uses_launch_tty;
+    struct termios tty_attributes;
+    string tty_path;
+    int tty_fd;
     int cur_frame_level;
     int cur_thread_num;
     Address cur_frame_address;
@@ -565,6 +569,8 @@ public:
         error_buffer_status (DEFAULT),
         state (IDebugger::NOT_STARTED),
         is_running (false),
+        uses_launch_tty (false),
+        tty_fd (-1),
         cur_frame_level (0),
         cur_thread_num (1),
         follow_fork_mode ("parent"),
@@ -573,6 +579,7 @@ public:
         enable_pretty_printing (true),
         pretty_printing_enabled_once (false)
     {
+        memset (&tty_attributes, 0, sizeof (tty_attributes));
 
         enable_pretty_printing =
             g_getenv ("NMV_DISABLE_PRETTY_PRINTING") == 0;
@@ -688,6 +695,37 @@ public:
         }
     }
 
+    /// Read the attributes of the low level tty used by Nemiver's
+    /// terminal and the inferior to communicate.  The attributes are
+    /// then stored memory.
+    void get_tty_attributes ()
+    {
+        LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+        if (uses_launch_tty && isatty (0)) {
+            tcgetattr (0, &tty_attributes);
+        } else if (tty_fd >= 0) {
+            tcgetattr (tty_fd,
+                       &tty_attributes);
+        }
+    }
+
+    /// Set the attributes (previously saved by get_tty_attributes)
+    /// from memory to the low level tty used by Nemiver's terminal
+    /// and the inferior to communicate.
+    void set_tty_attributes ()
+    {
+        LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+        if (uses_launch_tty && isatty (0)) {
+            tcsetattr (0, TCSANOW, &tty_attributes);
+        } else if (tty_fd >= 0){
+            tcsetattr (tty_fd,
+                       TCSANOW,
+                       &tty_attributes);
+        }
+    }
+
     bool launch_gdb_real (const vector<UString> a_argv)
     {
         RETURN_VAL_IF_FAIL (launch_program (a_argv,
@@ -872,6 +910,14 @@ public:
         LOG_DD ("issuing command: '" << a_command.value () << "': name: '"
                 << a_command.name () << "'");
 
+        if (a_command.name () == "re-run") {
+            // Before restarting the target, re-set the tty attributes
+            // so that the tty has a chance to comes back into cook
+            // mode.  Some targets might expect this behaviour.
+            LOG_DD ("Restoring tty attributes");
+            set_tty_attributes ();
+        }
+
         if (master_pty_channel->write
                 (a_command.value () + "\n") == Glib::IO_STATUS_NORMAL) {
             master_pty_channel->flush ();
@@ -3100,7 +3146,10 @@ GDBEngine::load_program (const UString &a_prog,
     vector<UString> search_paths;
     UString tty_path;
     return load_program (a_prog, a_args, a_working_dir,
-                         search_paths, tty_path, a_force);
+                         search_paths, tty_path, 
+                         /*slave_tty_fd*/-1,
+                         /*uses_launch_tty=*/false,
+                         a_force);
 }
 
 /// Load an inferior program to debug.
@@ -3117,7 +3166,11 @@ GDBEngine::load_program (const UString &a_prog,
 /// look for the source files of the objects that make up the inferior
 /// program.
 ///
-/// \param a_tty_path the tty path the inferior should use.
+/// \param a_slave_tty_path the tty path the inferior should use.
+///
+/// \param a_slave_tty_fd the file descriptor of the slave tty that is
+/// to be used by the inferior to communicate with the program using
+/// the current instance of GDBEngine.
 ///
 /// \param a_force if this is true and the command queue is stuck,
 /// clear it to force the loading of the inferior.
@@ -3126,7 +3179,9 @@ GDBEngine::load_program (const UString &a_prog,
                          const vector<UString> &a_argv,
                          const UString &a_working_dir,
                          const vector<UString> &a_source_search_dirs,
-                         const UString &a_tty_path,
+                         const UString &a_slave_tty_path,
+                         int a_slave_tty_fd,
+                         bool a_uses_launch_tty,
                          bool a_force)
 {
     LOG_FUNCTION_SCOPE_NORMAL_DD;
@@ -3136,13 +3191,20 @@ GDBEngine::load_program (const UString &a_prog,
 
     if (!m_priv->is_gdb_running ()) {
         vector<UString> gdb_opts;
+
+        // Read the tty attributes before we launch the target so that
+        // we can restore them later at exit time, to discard the tty
+        // changes that might be done by the target.
+        m_priv->tty_fd = a_slave_tty_fd;
+        m_priv->get_tty_attributes ();
+
         if (m_priv->launch_gdb_and_set_args (a_working_dir,
                                              a_source_search_dirs, 
                                              a_prog, a_argv,
                                              gdb_opts) == false)
             return false;
 
-        Command command;
+        m_priv->uses_launch_tty = a_uses_launch_tty;
 
         // In case we are restarting GDB after a crash, the command
         // queue might be stuck.  Let's restart it.
@@ -3194,7 +3256,7 @@ GDBEngine::load_program (const UString &a_prog,
             queue_command (command);
         }
     }
-    m_priv->set_tty_path (a_tty_path, "load-program");
+    m_priv->set_tty_path (a_slave_tty_path, "load-program");
     return true;
 }
 
@@ -4360,6 +4422,7 @@ GDBEngine::stop_target ()
     return  (kill (m_priv->gdb_pid, SIGINT) == 0);
 }
 
+/// Stop the inferior and exit GDB.  Do the necessary book keeping.
 void
 GDBEngine::exit_engine ()
 {
@@ -4379,6 +4442,10 @@ GDBEngine::exit_engine ()
     //send the lethal command and run the event loop to flush everything.
     m_priv->issue_command (Command ("quit"), false);
     set_state (IDebugger::NOT_STARTED);
+
+    // Set the tty attribute back into the state it was before we
+    // connected to the target.
+    m_priv->set_tty_attributes ();
 }
 
 void
diff --git a/src/dbgengine/nmv-gdb-engine.h b/src/dbgengine/nmv-gdb-engine.h
index c027968..135992f 100644
--- a/src/dbgengine/nmv-gdb-engine.h
+++ b/src/dbgengine/nmv-gdb-engine.h
@@ -292,7 +292,9 @@ public:
                        const vector<UString> &a_argv,
                        const UString &working_dir,
                        const vector<UString> &a_source_search_dirs,
-                       const UString &a_tty_path,
+                       const UString &a_slave_tty_path,
+		       int a_slave_tty_fd,
+		       bool a_uses_launch_tty,
 		       bool a_force);
 
     void load_core_file (const UString &a_prog_file,
diff --git a/src/dbgengine/nmv-i-debugger.h b/src/dbgengine/nmv-i-debugger.h
index f9fa525..5356745 100644
--- a/src/dbgengine/nmv-i-debugger.h
+++ b/src/dbgengine/nmv-i-debugger.h
@@ -1273,7 +1273,9 @@ public:
                  const vector<UString> &a_argv,
                  const UString &working_dir,
                  const vector<UString> &a_source_search_dirs,
-                 const UString &a_tty_path,
+                 const UString &a_slave_tty_path,
+                 int a_slave_tty_fd,
+                 bool a_uses_launch_tty = false,
                  bool a_force = false) = 0;
 
     virtual void load_core_file (const UString &a_prog_file,
diff --git a/src/persp/dbgperspective/nmv-dbg-perspective.cc b/src/persp/dbgperspective/nmv-dbg-perspective.cc
index b2cc7c6..b7ad484 100644
--- a/src/persp/dbgperspective/nmv-dbg-perspective.cc
+++ b/src/persp/dbgperspective/nmv-dbg-perspective.cc
@@ -2105,8 +2105,8 @@ DBGPerspective::on_shutdown_signal ()
         return;
     }
 
-    // stop the debugger so that the target executable doesn't go on running
-    // after we shut down
+    // stop the debugger so that the target executable doesn't go on
+    // running after we shut down
     debugger ()->exit_engine ();
 
     if (m_priv->reused_session) {
@@ -6075,6 +6075,8 @@ DBGPerspective::execute_program
     if (dbg_engine->load_program (prog, a_args, a_cwd,
                                   source_search_dirs,
                                   get_terminal_name (),
+                                  uses_launch_terminal (),
+                                  get_terminal ().slave_pty (),
                                   a_restarting
                                   ? true
                                   : false) == false) {
@@ -8159,6 +8161,16 @@ DBGPerspective::get_terminal_box ()
     return *m_priv->terminal_box;
 }
 
+/// Return the path name for the tty device that the debugging
+/// perspective uses to communicate with the standard tty of the and
+/// the inferior program.
+///
+/// If Nemiver is using the terminal from which it was launch (rather
+/// than its own terminal widget), the name returned is the path name
+/// for the tty device of that "launch terminal".
+///
+/// Note that this really is the path of the device created for the
+/// slave side of the relevant pseudo terminal.
 UString
 DBGPerspective::get_terminal_name ()
 {
diff --git a/src/uicommon/nmv-terminal.cc b/src/uicommon/nmv-terminal.cc
index e925f67..81cc859 100644
--- a/src/uicommon/nmv-terminal.cc
+++ b/src/uicommon/nmv-terminal.cc
@@ -295,6 +295,16 @@ Terminal::adjustment () const
     return m_priv->adjustment;
 }
 
+/// Return the file descriptor of the slave pseudo tty used by the the
+/// proces that would want to communicate with this terminal.
+int
+Terminal::slave_pty () const
+{
+    THROW_IF_FAIL (m_priv);
+    THROW_IF_FAIL (m_priv->slave_pty);
+    return m_priv->slave_pty;
+}
+
 UString
 Terminal::slave_pts_name () const
 {
diff --git a/src/uicommon/nmv-terminal.h b/src/uicommon/nmv-terminal.h
index 6f5b9ed..d8c075d 100644
--- a/src/uicommon/nmv-terminal.h
+++ b/src/uicommon/nmv-terminal.h
@@ -66,6 +66,7 @@ public:
     ~Terminal ();
     Gtk::Widget& widget () const;
     Glib::RefPtr<Gtk::Adjustment> adjustment () const;
+    int slave_pty () const;
     UString slave_pts_name () const;
     void modify_font (const Pango::FontDescription &font_desc);
     void feed (const UString &a_text);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]