bug-gdb
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH]: machine interface not flushing properly


From: David Whedon
Subject: [PATCH]: machine interface not flushing properly
Date: Tue, 15 May 2001 17:03:44 -0700
User-agent: Mutt/1.2.5i

Hi,

I think I found a buglet in the gdbmi interface.  I've been going back and forth
on this but I'm fairly convinced my little code is right.

It appears as though we're not getting raw_stdout flushed properly.  I have
observed this behavior with gdb 5.0 as well as current (updated yesterday) cvs.
The wierd thing is that it looks like gdbmi is intentianally not flushing the
way I think it should, which causes me to doubt myself.

Here is an example of bad behavior (the example program is included later in the
message):

$ gcc gdbmi_bug.c
$ ./a.out
|GNU gdb 5.0 (MI_OUT)|
|Copyright 2001 Free Software Foundation, Inc.|
|GDB is free software, covered by the GNU General Public License, and you are|
|welcome to change it and/or distribute copies of it under certain conditions.|
|Type "show copying" to see the conditions.|
|There is absolutely no warranty for GDB.  Type "show warranty" for details.|
Error reading from gdb
We timeout out, that's a bug!
$


Then applying itty bitty patch you'll see later we get:
$ ./a.out
|GNU gdb 5.0 (MI_OUT)|
|Copyright 2001 Free Software Foundation, Inc.|
|GDB is free software, covered by the GNU General Public License, and you are|
|welcome to change it and/or distribute copies of it under certain conditions.|
|Type "show copying" to see the conditions.|
|There is absolutely no warranty for GDB.  Type "show warranty" for details.|
|This GDB was configured as "i686-pc-linux-gnu".|
|(gdb) |
No bug!
$


It is actually only the last chunk of the patch that is fixing the above bug but
I suspect that the other chunks are necessary too.

--- mi-main.c.orig      Mon May 14 17:30:02 2001
+++ mi-main.c   Tue May 15 16:56:14 2001
@@ -1159,6 +1159,7 @@
 
   gdb_flush (raw_stdout);
   fputs_unfiltered ("(gdb) \n", raw_stdout);
+  gdb_flush (raw_stdout);
   /* print any buffered hook code */
   /* ..... */
 }
@@ -1289,6 +1290,7 @@
        fputs_unfiltered (last_async_command, raw_stdout);
       fputs_unfiltered ("^running\n", raw_stdout);
       fputs_unfiltered ("(gdb) \n", raw_stdout);
+      gdb_flush (raw_stdout);
     }
   else
     {
@@ -1330,6 +1332,7 @@
   mi_out_put (uiout, raw_stdout);
   fputs_unfiltered ("\n", raw_stdout);
   fputs_unfiltered ("(gdb) \n", raw_stdout);
+  gdb_flush (raw_stdout);
   do_exec_cleanups (ALL_CLEANUPS);
 }
 
@@ -1457,6 +1460,7 @@
 
   /* Tell the world that we're alive */
   fputs_unfiltered ("(gdb) \n", raw_stdout);
+  gdb_flush (raw_stdout);
 
   if (!event_loop_p)
     simplified_command_loop (mi_input, mi_execute_command);


Thanks for your time,

David


Here's the code that demonstrates the buglet, you will have to change GDB_PATH
to point to the gdb you want to test.


/*
   Copyright (c) 2001 Gordian 
   file - gdbmi_bug.c
   author - David Whedon <address@hidden>
   purpose - This is the interface to gdb used by the superfut.
   
 */
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <signal.h>
#include <regex.h>
#include <stdarg.h>

#define GDB_PATH "/home/davidw/work/gdb/gdb/gdb"
/*#define GDB_PATH "/usr/local/gordian/bin/arm-gordian-coff-gdb"*/

/* We communicate with gdb through two pipes */
static int fd_to_gdb[2] = { 0 };        /* 0=read 1=write */
static int fd_from_gdb[2] = { 0 };      /* 0=read 1=write */
static pid_t gdb_pid = 0;


/* 
   read characters from gdb. Stop at the first newline or if more that 'size'
   characters would be read or if an inter character gap of > 100 usec is
   observed.  Place the read characters in 's'.

   If a newline is found, replace it with a '\0' and return the number of bytes
   read not including the newline. 
   
   returns -1 on error, timeout, and/or no newline found
*/
static int
gdbmi_read (char *s, int size)
{
  int bytes = 0, rv;
  fd_set readfds;
  struct timeval tv;

  if (!fd_from_gdb[0])
    return -1;

  FD_ZERO (&readfds);
  FD_SET (fd_from_gdb[0], &readfds);

  while (bytes < size)
    {

      tv.tv_sec = 3;
      tv.tv_usec = 0;

      if ((rv = select (fd_from_gdb[0] + 1, &readfds, NULL, NULL, &tv)) == -1)
        {
          perror ("select");
          return -1;
        }

      if (rv == 0)
        /* timeout, nothing available */
        break;

      if ((rv = read (fd_from_gdb[0], &s[bytes], 1)) <= 0)
        {
          perror ("read");
          return -1;
        }

      bytes++;

      if (s[bytes - 1] == '\n')
        {
          s[bytes - 1] = '\0';
          return bytes - 1;
        }
    }
  fprintf(stderr, "Error reading from gdb\n");
  return -1;
}


/*
  Attempt to start gdb.  
  Initialize two pipes (fd_to_gdb and fd_to_gdb) that we will use to control
  gdb. Read from gdb until we get the first (gdb) prompt.

  returns 0 on success
  returns -1 on failure
 */
int
main ()
{
  char buffer[512];
  struct stat stat_buf;
  int rv;

  if (stat (GDB_PATH, &stat_buf))
    {
      perror ("stat");
      return -1;
    }

  if (pipe (fd_to_gdb) || pipe (fd_from_gdb))
    {
      perror ("pipe");
      return -1;
    }

  if ((gdb_pid = fork ()) == 0)
    {

      if (close (fd_to_gdb[1]) || close (fd_from_gdb[0]))
        {
          perror ("close");
          exit (1);
        }

      if ((dup2 (fd_to_gdb[0], 0) == -1) || (dup2 (fd_from_gdb[1], 1) == -1))
        {
          perror ("dup2");
          exit (1);
        }

      if (execl (GDB_PATH, GDB_PATH, "--interpreter=mi", "--nx", "--nw", NULL)
          != 0)
        perror ("execv");

      exit (1);
    }
  else if (gdb_pid == -1)
    {
      perror ("fork");
      return -1;
    }

  if (close (fd_to_gdb[0]) || close (fd_from_gdb[1]))
    {
      perror ("close");
      goto error;
    }


  /* read intro up to first '(gdb) ' prompt */
  while ((rv = gdbmi_read (buffer, sizeof (buffer))) >= 0)
    {
      fprintf (stderr, "|%s|\n", buffer);
      if (strstr(buffer, "(gdb) "))
          break;
    }

  if (rv == -1)
     fprintf(stderr, "We timeout out, that's a bug!\n");
  else
     fprintf(stderr, "No bug!\n");
error:

}



reply via email to

[Prev in Thread] Current Thread [Next in Thread]