[PATCH v2 23/25] Handle UI terminal closed

Pedro Alves
2016-03-21T15:27:51Z

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/event-top.c | 25 ++++++++++++++++++-------
gdb/top.c | 31 +++++++++++++++++++++++++++++++
gdb/top.h | 1 +
3 files changed, 50 insertions(+), 7 deletions(-)

diff --git a/gdb/event-top.c b/gdb/event-top.c
index 69f6be7..39b9633 100644
--- a/gdb/event-top.c
+++ b/gdb/event-top.c
@@ -420,19 +420,30 @@ 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
{
+ /* Switch to the UI whose input descriptor woke up the event
+ loop. */
+ current_ui = ui;
+
do
{
call_stdin_event_handler_again_p = 0;
diff --git a/gdb/top.c b/gdb/top.c
index 12064bc..7d6d7cb 100644
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -282,6 +282,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 df76204..bac5a33 100644
--- a/gdb/top.h
+++ b/gdb/top.h
@@ -161,6 +161,7 @@ extern void switch_thru_all_uis_next (struct switch_thru_all_uis *state);
for (UI = ui_list; UI; UI = UI->next) \

extern struct ui *new_ui (FILE *instream, FILE *outstream, FILE *errstream);
+extern void delete_ui (struct ui *todel);

extern void restore_ui_cleanup (void *data);

--
2.5.0