[PATCH v3 27/34] Handle UI's terminal closing

Pedro Alves
2016-05-06T12:45:26Z

Without this, GDB exits if a secondary UIs terminal/input stream is
closed:

$ ./gdb -ex "new-ui mi /dev/pts/6"
New UI allocated
<<< close /dev/pts/6
(gdb) Error detected on fd 9
$

We want that for the main UI, but not secondary UIs.

gdb/ChangeLog:
yyyy-mm-dd Pedro Alves <palves@redhat.com>

* event-top.c (stdin_event_handler): Don't quit gdb if it was a
secondary UI's input stream that closed. Instead, just delete the
UI.
---
gdb/event-top.c | 42 +++++++++++++++++++++++++++---------------
gdb/top.c | 31 +++++++++++++++++++++++++++++++
gdb/top.h | 1 +
3 files changed, 59 insertions(+), 15 deletions(-)

diff --git a/gdb/event-top.c b/gdb/event-top.c
index 318da1d..777823e 100644
--- a/gdb/event-top.c
+++ b/gdb/event-top.c
@@ -508,33 +508,45 @@ stdin_event_handler (int error, gdb_client_data client_data)
{
struct ui *ui = (struct ui *) client_data;

- /* Switch to the UI whose input descriptor woke up the event
- loop. */
- current_ui = ui;
-
if (error)
{
- printf_unfiltered (_("error detected on stdin\n"));
+ /* Switch to the main UI, so diagnostics always go there. */
+ current_ui = main_ui;
+
delete_file_handler (ui->input_fd);
- /* If stdin died, we may as well kill gdb. */
- quit_command ((char *) 0, stdin == ui->instream);
+ if (main_ui == ui)
+ {
+ /* If stdin died, we may as well kill gdb. */
+ printf_unfiltered (_("error detected on stdin\n"));
+ quit_command ((char *) 0, stdin == ui->instream);
+ }
+ else
+ {
+ /* Simply delete the UI. */
+ delete_ui (ui);
+ }
}
else
{
- /* This makes sure a ^C immediately followed by further input is
- always processed in that order. E.g,. with input like
- "^Cprint 1\n", the SIGINT handler runs, marks the async signal
- handler, and then select/poll may return with stdin ready,
- instead of -1/EINTR. The
- gdb.base/double-prompt-target-event-error.exp test exercises
- this. */
+ /* Switch to the UI whose input descriptor woke up the event
+ loop. */
+ current_ui = ui;
+
+ /* This makes sure a ^C immediately followed by further input is
+ always processed in that order. E.g,. with input like
+ "^Cprint 1\n", the SIGINT handler runs, marks the async
+ signal handler, and then select/poll may return with stdin
+ ready, instead of -1/EINTR. The
+ gdb.base/double-prompt-target-event-error.exp test exercises
+ this. */
QUIT;

do
{
call_stdin_event_handler_again_p = 0;
ui->call_readline (client_data);
- } while (call_stdin_event_handler_again_p != 0);
+ }
+ while (call_stdin_event_handler_again_p != 0);
}
}

diff --git a/gdb/top.c b/gdb/top.c
index c5e237d..5883875 100644
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -286,6 +286,37 @@ new_ui (FILE *instream, FILE *outstream, FILE *errstream)
return ui;
}

+static void
+free_ui (struct ui *ui)
+{
+ ui_file_delete (ui->m_gdb_stdin);
+ ui_file_delete (ui->m_gdb_stdout);
+ ui_file_delete (ui->m_gdb_stderr);
+
+ xfree (ui);
+}
+
+void
+delete_ui (struct ui *todel)
+{
+ struct ui *ui, *uiprev;
+
+ uiprev = NULL;
+
+ for (ui = ui_list; ui != NULL; uiprev = ui, ui = ui->next)
+ if (ui == todel)
+ break;
+
+ gdb_assert (ui != NULL);
+
+ if (uiprev != NULL)
+ uiprev->next = ui->next;
+ else
+ ui_list = ui->next;
+
+ free_ui (ui);
+}
+
/* Handler for SIGHUP. */

#ifdef SIGHUP
diff --git a/gdb/top.h b/gdb/top.h
index c933d6b..a0fa391 100644
--- a/gdb/top.h
+++ b/gdb/top.h
@@ -175,6 +175,7 @@ extern void switch_thru_all_uis_next (struct switch_thru_all_uis *state);

/* Create a new UI. */
extern struct ui *new_ui (FILE *instream, FILE *outstream, FILE *errstream);
+extern void delete_ui (struct ui *todel);

/* Cleanup that restores the current UI. */
extern void restore_ui_cleanup (void *data);
--
2.5.5