Restore terminal state in mi_thread_exit (PR gdb/17627)

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>
This commit is contained in:
Simon Marchi 2014-12-10 13:03:47 -05:00
parent f4943d8253
commit 1abf3a1437
4 changed files with 50 additions and 0 deletions

View 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.

View 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. */

View 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)
{

View 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. */