Handle UI's terminal closing
authorPedro Alves <palves@redhat.com>
Tue, 21 Jun 2016 00:11:54 +0000 (01:11 +0100)
committerPedro Alves <palves@redhat.com>
Tue, 21 Jun 2016 00:11:54 +0000 (01:11 +0100)
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:
2016-06-21  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/ChangeLog
gdb/event-top.c
gdb/top.c
gdb/top.h

index b21f7c1..22b369d 100644 (file)
@@ -1,5 +1,11 @@
 2016-06-21  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.
+
+2016-06-21  Pedro Alves  <palves@redhat.com>
+
        * event-top.c (main_ui_): Delete.
        (main_ui, current_ui, ui_list): No longer initialize here.
        * main.c (captured_main): UI initialization code factored out to
index 318da1d..777823e 100644 (file)
@@ -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);
     }
 }
 
index c5e237d..5883875 100644 (file)
--- 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
index 9766cd5..7fbd187 100644 (file)
--- 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);