Don't rely on immediate_quit in command_line_input
authorPedro Alves <palves@redhat.com>
Tue, 12 Apr 2016 15:49:29 +0000 (16:49 +0100)
committerPedro Alves <palves@redhat.com>
Tue, 12 Apr 2016 15:49:29 +0000 (16:49 +0100)
AFAICS, immediate_quit was only needed here nowdays to be able to
interrupt gdb_readline_no_editing.

command_line_input can also take the gdb_readline_wrapper path, but
since that is built on top of the event loop (gdb_select / poll and
asynchronous signal handlers), it can be interrupted.

gdb/ChangeLog:
2016-04-12  Pedro Alves  <palves@redhat.com>

* top.c: Include "gdb_select.h".
(gdb_readline_no_editing): Wait for input with gdb_select instead
of blocking in fgetc.
(command_line_input): Don't set immediate_quit.

gdb/ChangeLog
gdb/top.c

index 87f7679..d6e2fe1 100644 (file)
@@ -1,3 +1,10 @@
+2016-04-12  Pedro Alves  <palves@redhat.com>
+
+       * top.c: Include "gdb_select.h".
+       (gdb_readline_no_editing): Wait for input with gdb_select instead
+       of blocking in fgetc.
+       (command_line_input): Don't set immediate_quit.
+
 2016-04-08  Martin Galvan  <martin.galvan@tallertechnologies.com>
 
        * value.c (value_next): Make pass-by-reference parameters const-correct.
index 89fe832..90a3f48 100644 (file)
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -51,6 +51,7 @@
 #include "filenames.h"
 #include "frame.h"
 #include "buffer.h"
+#include "gdb_select.h"
 
 /* readline include files.  */
 #include "readline/readline.h"
@@ -592,6 +593,10 @@ static char *
 gdb_readline_no_editing (const char *prompt)
 {
   struct buffer line_buffer;
+  /* Read from stdin if we are executing a user defined command.  This
+     is the right thing for prompt_for_continue, at least.  */
+  FILE *stream = instream != NULL ? instream : stdin;
+  int fd = fileno (stream);
 
   buffer_init (&line_buffer);
 
@@ -607,10 +612,26 @@ gdb_readline_no_editing (const char *prompt)
   while (1)
     {
       int c;
+      int numfds;
+      fd_set readfds;
 
-      /* Read from stdin if we are executing a user defined command.
-         This is the right thing for prompt_for_continue, at least.  */
-      c = fgetc (instream ? instream : stdin);
+      QUIT;
+
+      /* Wait until at least one byte of data is available.  Control-C
+        can interrupt gdb_select, but not fgetc.  */
+      FD_ZERO (&readfds);
+      FD_SET (fd, &readfds);
+      if (gdb_select (fd + 1, &readfds, NULL, NULL, NULL) == -1)
+       {
+         if (errno == EINTR)
+           {
+             /* If this was ctrl-c, the QUIT above handles it.  */
+             continue;
+           }
+         perror_with_name (("select"));
+       }
+
+      c = fgetc (stream);
 
       if (c == EOF)
        {
@@ -1048,10 +1069,6 @@ command_line_input (const char *prompt_arg, int repeat, char *annotation_suffix)
   /* Starting a new command line.  */
   cmd_line_buffer.used_size = 0;
 
-  /* Control-C quits instantly if typed while in this loop
-     since it should not wait until the user types a newline.  */
-  immediate_quit++;
-  QUIT;
 #ifdef STOP_SIGNAL
   if (job_control)
     signal (STOP_SIGNAL, handle_stop_sig);
@@ -1109,7 +1126,6 @@ command_line_input (const char *prompt_arg, int repeat, char *annotation_suffix)
   if (job_control)
     signal (STOP_SIGNAL, SIG_DFL);
 #endif
-  immediate_quit--;
 
   return cmd;
 }