Restore terminal state in mi_thread_exit (PR gdb/17627)
authorSimon Marchi <simon.marchi@ericsson.com>
Wed, 10 Dec 2014 18:03:47 +0000 (13:03 -0500)
committerSimon Marchi <simon.marchi@ericsson.com>
Wed, 10 Dec 2014 18:03:47 +0000 (13:03 -0500)
When a thread exits, the terminal is left in mode "terminal_is_ours"
while the target executes.  This patch fixes that.

We need to manually restore the terminal setting in this particular
observer.  In the case of the other MI observers that call
target_terminal_ours, gdb will end up resuming the inferior later in the
execution and call target_terminal_inferior.  In the case of the thread
exit event, we still need to call target_terminal_ours to be able to
print something, but there is nothing that gdb will need to resume after
that. We therefore need to call target_terminal_inferior ourselves.

gdb/ChangeLog:

PR gdb/17627
* target.c (cleanup_restore_target_terminal): New function.
(make_cleanup_restore_target_terminal): New function.
* target.h (make_cleanup_restore_target_terminal): New
declaration.
* mi/mi-interp.c (mi_thread_exit): Use the new cleanup.

Signed-off-by: Simon Marchi <simon.marchi@ericsson.com>
gdb/ChangeLog
gdb/mi/mi-interp.c
gdb/target.c
gdb/target.h

index ad845a75279f394358c384273a4b5176808d9c91..4aeb0cc8a9bbd72fd0d23af302a403851c33fef2 100644 (file)
@@ -1,3 +1,11 @@
+2014-12-10  Simon Marchi  <simon.marchi@ericsson.com>
+
+       PR gdb/17627
+       * target.c (cleanup_restore_target_terminal): New function.
+       (make_cleanup_restore_target_terminal): New function.
+       * target.h (make_cleanup_restore_target_terminal): New declaration.
+       * mi/mi-interp.c (mi_thread_exit): Use the new cleanup.
+
 2014-12-08  Doug Evans  <dje@google.com>
 
        * python/py-objfile.c (objfpy_get_owner): Increment refcount of result.
index df2b558291f34b1a2ee712e309bfcbd6057c6679..60f066660a026944367a58d35204847ae34c3279 100644 (file)
@@ -386,6 +386,7 @@ mi_thread_exit (struct thread_info *t, int silent)
 {
   struct mi_interp *mi;
   struct inferior *inf;
+  struct cleanup *old_chain;
 
   if (silent)
     return;
@@ -393,11 +394,14 @@ mi_thread_exit (struct thread_info *t, int silent)
   inf = find_inferior_pid (ptid_get_pid (t->ptid));
 
   mi = top_level_interpreter_data ();
+  old_chain = make_cleanup_restore_target_terminal ();
   target_terminal_ours ();
   fprintf_unfiltered (mi->event_channel, 
                      "thread-exited,id=\"%d\",group-id=\"i%d\"",
                      t->num, inf->num);
   gdb_flush (mi->event_channel);
+
+  do_cleanups (old_chain);
 }
 
 /* Emit notification on changing the state of record.  */
index ab5f2b9f36d35f9568026975268bf6aacfb1db9a..7161e62acc3a8feff6f3c952e31c7c5ba0a6d75c 100644 (file)
@@ -528,6 +528,40 @@ target_supports_terminal_ours (void)
   return 0;
 }
 
+/* Restore the terminal to its previous state (helper for
+   make_cleanup_restore_target_terminal). */
+
+static void
+cleanup_restore_target_terminal (void *arg)
+{
+  enum terminal_state *previous_state = arg;
+
+  switch (*previous_state)
+    {
+    case terminal_is_ours:
+      target_terminal_ours ();
+      break;
+    case terminal_is_ours_for_output:
+      target_terminal_ours_for_output ();
+      break;
+    case terminal_is_inferior:
+      target_terminal_inferior ();
+      break;
+    }
+}
+
+/* See target.h. */
+
+struct cleanup *
+make_cleanup_restore_target_terminal (void)
+{
+  enum terminal_state *ts = xmalloc (sizeof (*ts));
+
+  *ts = terminal_state;
+
+  return make_cleanup_dtor (cleanup_restore_target_terminal, ts, xfree);
+}
+
 static void
 tcomplain (void)
 {
index d363b61bc32bb856b85bc9d49cc97ca2577d7c5a..cff146afc4dc9afdeeb0f694a0573c493808e3ec 100644 (file)
@@ -1413,6 +1413,10 @@ extern void target_terminal_ours (void);
 
 extern int target_supports_terminal_ours (void);
 
+/* Make a cleanup that restores the state of the terminal to the current
+   state.  */
+extern struct cleanup *make_cleanup_restore_target_terminal (void);
+
 /* Print useful information about our terminal status, if such a thing
    exists.  */