[Top][All Lists]
[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:
}
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [PATCH]: machine interface not flushing properly,
David Whedon <=