This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[commit] call readchar instead of read in gdbserver:putpkt_binary_1


Hi.

I was getting gdbserver connection errors exhibited by the following logs.
The key thing to note is that while gdb sent <qSupported><qSupported>+
gdbserver received <qSupported>+<qSupported>
grep for <<<---xxx

gdb side of bug:

gdb$ ./gdb -nx ~/hello.x64
GNU gdb (GDB) 7.1.50.20100425-cvs
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/dje/hello.x64...done.
(gdb) set debug remote 1
(gdb) tar rem :1234
Remote debugging using :1234
Sending packet: $qSupported#37...Sending packet: $qSupported#37...Ack
Packet received: PacketSize=3fff;QPassSignals+;qXfer:libraries:read+;qXfer:auxv:read+;qXfer:spu:read+;qXfer:spu:write+;qXfer:siginfo:read+;qXfer:siginfo:write+;qXfer:features:read+;QStartNoAckMode+;qXfer:osdata:read+;multiprocess+;QNonStop+;qXfer:threads:read+;ConditionalTracepoints+;TraceStateVariables+;TracepointSource+;DisconnectedTracing+
Packet qSupported (supported-packets) is supported
Sending packet: $QStartNoAckMode#b0...Ack
Packet received: PacketSize=3fff;QPassSignals+;qXfer:libraries:read+;qXfer:auxv:read+;qXfer:spu:read+;qXfer:spu:write+;qXfer:siginfo:read+;qXfer:siginfo:write+;qXfer:features:read+;QStartNoAckMode+;qXfer:osdata:read+;multiprocess+;QNonStop+;qXfer:threads:read+;ConditionalTracepoints+;TraceStateVariables+;TracepointSource+;DisconnectedTracing+
Sending packet: $Hg0#df...Packet received: PacketSize=3fff;QPassSignals+;qXfer:libraries:read+;qXfer:auxv:read+;qXfer:spu:read+;qXfer:spu:write+;qXfer:siginfo:read+;qXfer:siginfo:write+;qXfer:features:read+;QStartNoAckMode+;qXfer:osdata:read+;multiprocess+;QNonStop+;qXfer:threads:read+;ConditionalTracepoints+;TraceStateVariables+;TracepointSource+;DisconnectedTracing+
Sending packet: $qXfer:features:read:target.xml:0,fff#7d...Packet received: PacketSize=3fff;QPassSignals+;qXfer:libraries:read+;qXfer:auxv:read+;qXfer:spu:read+;qXfer:spu:write+;qXfer:siginfo:read+;qXfer:siginfo:write+;qXfer:features:read+;QStartNoAckMode+;qXfer:osdata:read+;multiprocess+;QNonStop+;qXfer:threads:read+;ConditionalTracepoints+;TraceStateVariables+;TracepointSource+;DisconnectedTracing+
Unknown remote qXfer reply: PacketSize=3fff;QPassSignals+;qXfer:libraries:read+;qXfer:auxv:read+;qXfer:spu:read+;qXfer:spu:write+;qXfer:siginfo:read+;qXfer:siginfo:write+;qXfer:features:read+;QStartNoAckMode+;qXfer:osdata:read+;multiprocess+;QNonStop+;qXfer:threads:read+;ConditionalTracepoints+;TraceStateVariables+;TracepointSource+;DisconnectedTracing+
(gdb) q

gdbserver side of bug:

gdb$ ./gdbserver/gdbserver --remote-debug :1234 ~/hello.x64
Process /home/dje/hello.x64 created; pid = 7639
Listening on port 1234
Remote debugging from host 127.0.0.1
[getpkt: discarding char '+']
getpkt ("qSupported");  [sending ack] 
[sent ack]
putpkt ("$PacketSize=3fff;QPassSignals+;qXfer:libraries:read+;qXfer:auxv:read+;qXfer:spu:read+;qXfer:spu:write+;qXfer:siginfo:read+;qXfer:siginfo:write+;qXfer:features:read+;QStartNoAckMode+;qXfer:osdata:read+;multiprocess+;QNonStop+;qXfer:threads:read+;ConditionalTracepoints+;TraceStateVariables+;TracepointSource+;DisconnectedTracing+#77"); [looking for ack]
[received '+' (0x2b)] <<<---xxx
getpkt ("qSupported");  [sending ack] 
[sent ack]
putpkt ("$PacketSize=3fff;QPassSignals+;qXfer:libraries:read+;qXfer:auxv:read+;qXfer:spu:read+;qXfer:spu:write+;qXfer:siginfo:read+;qXfer:siginfo:write+;qXfer:features:read+;QStartNoAckMode+;qXfer:osdata:read+;multiprocess+;QNonStop+;qXfer:threads:read+;ConditionalTracepoints+;TraceStateVariables+;TracepointSource+;DisconnectedTracing+#77"); [looking for ack]
[received '$' (0x24)]
putpkt ("$PacketSize=3fff;QPassSignals+;qXfer:libraries:read+;qXfer:auxv:read+;qXfer:spu:read+;qXfer:spu:write+;qXfer:siginfo:read+;qXfer:siginfo:write+;qXfer:features:read+;QStartNoAckMode+;qXfer:osdata:read+;multiprocess+;QNonStop+;qXfer:threads:read+;ConditionalTracepoints+;TraceStateVariables+;TracepointSource+;DisconnectedTracing+#77"); [looking for ack]
[received 'Q' (0x51)]
putpkt ("$PacketSize=3fff;QPassSignals+;qXfer:libraries:read+;qXfer:auxv:read+;qXfer:spu:read+;qXfer:spu:write+;qXfer:siginfo:read+;qXfer:siginfo:write+;qXfer:features:read+;QStartNoAckMode+;qXfer:osdata:read+;multiprocess+;QNonStop+;qXfer:threads:read+;ConditionalTracepoints+;TraceStateVariables+;TracepointSource+;DisconnectedTracing+#77"); [looking for ack]
[received 'S' (0x53)]
putpkt ("$PacketSize=3fff;QPassSignals+;qXfer:libraries:read+;qXfer:auxv:read+;qXfer:spu:read+;qXfer:spu:write+;qXfer:siginfo:read+;qXfer:siginfo:write+;qXfer:features:read+;QStartNoAckMode+;qXfer:osdata:read+;multiprocess+;QNonStop+;qXfer:threads:read+;ConditionalTracepoints+;TraceStateVariables+;TracepointSource+;DisconnectedTracing+#77"); [looking for ack]
[received 't' (0x74)]
putpkt ("$PacketSize=3fff;QPassSignals+;qXfer:libraries:read+;qXfer:auxv:read+;qXfer:spu:read+;qXfer:spu:write+;qXfer:siginfo:read+;qXfer:siginfo:write+;qXfer:features:read+;QStartNoAckMode+;qXfer:osdata:read+;multiprocess+;QNonStop+;qXfer:threads:read+;ConditionalTracepoints+;TraceStateVariables+;TracepointSource+;DisconnectedTracing+#77"); [looking for ack]
[received 'a' (0x61)]
putpkt ("$PacketSize=3fff;QPassSignals+;qXfer:libraries:read+;qXfer:auxv:read+;qXfer:spu:read+;qXfer:spu:write+;qXfer:siginfo:read+;qXfer:siginfo:write+;qXfer:features:read+;QStartNoAckMode+;qXfer:osdata:read+;multiprocess+;QNonStop+;qXfer:threads:read+;ConditionalTracepoints+;TraceStateVariables+;TracepointSource+;DisconnectedTracing+#77"); [looking for ack]
[received 'r' (0x72)]
putpkt ("$PacketSize=3fff;QPassSignals+;qXfer:libraries:read+;qXfer:auxv:read+;qXfer:spu:read+;qXfer:spu:write+;qXfer:siginfo:read+;qXfer:siginfo:write+;qXfer:features:read+;QStartNoAckMode+;qXfer:osdata:read+;multiprocess+;QNonStop+;qXfer:threads:read+;ConditionalTracepoints+;TraceStateVariables+;TracepointSource+;DisconnectedTracing+#77"); [looking for ack]
[received 't' (0x74)]
putpkt ("$PacketSize=3fff;QPassSignals+;qXfer:libraries:read+;qXfer:auxv:read+;qXfer:spu:read+;qXfer:spu:write+;qXfer:siginfo:read+;qXfer:siginfo:write+;qXfer:features:read+;QStartNoAckMode+;qXfer:osdata:read+;multiprocess+;QNonStop+;qXfer:threads:read+;ConditionalTracepoints+;TraceStateVariables+;TracepointSource+;DisconnectedTracing+#77"); [looking for ack]
[received 'N' (0x4e)]
putpkt ("$PacketSize=3fff;QPassSignals+;qXfer:libraries:read+;qXfer:auxv:read+;qXfer:spu:read+;qXfer:spu:write+;qXfer:siginfo:read+;qXfer:siginfo:write+;qXfer:features:read+;QStartNoAckMode+;qXfer:osdata:read+;multiprocess+;QNonStop+;qXfer:threads:read+;ConditionalTracepoints+;TraceStateVariables+;TracepointSource+;DisconnectedTracing+#77"); [looking for ack]
[received 'o' (0x6f)]
putpkt ("$PacketSize=3fff;QPassSignals+;qXfer:libraries:read+;qXfer:auxv:read+;qXfer:spu:read+;qXfer:spu:write+;qXfer:siginfo:read+;qXfer:siginfo:write+;qXfer:features:read+;QStartNoAckMode+;qXfer:osdata:read+;multiprocess+;QNonStop+;qXfer:threads:read+;ConditionalTracepoints+;TraceStateVariables+;TracepointSource+;DisconnectedTracing+#77"); [looking for ack]
[received 'A' (0x41)]
putpkt ("$PacketSize=3fff;QPassSignals+;qXfer:libraries:read+;qXfer:auxv:read+;qXfer:spu:read+;qXfer:spu:write+;qXfer:siginfo:read+;qXfer:siginfo:write+;qXfer:features:read+;QStartNoAckMode+;qXfer:osdata:read+;multiprocess+;QNonStop+;qXfer:threads:read+;ConditionalTracepoints+;TraceStateVariables+;TracepointSource+;DisconnectedTracing+#77"); [looking for ack]
[received 'c' (0x63)]
putpkt(write): Broken pipe
[getpkt: discarding char 'k']
[getpkt: discarding char 'M']
[getpkt: discarding char 'o']
[getpkt: discarding char 'd']
[getpkt: discarding char 'e']
[getpkt: discarding char '#']
[getpkt: discarding char 'b']
[getpkt: discarding char '0']
[getpkt: discarding char '+']
getpkt ("Hg0");  [sending ack] 
[sent ack]
putpkt(write): Broken pipe
getpkt ("qXfer:features:read:target.xml:0,fff");  [sending ack] 
[sent ack]
putpkt(write): Broken pipe
readchar: Got EOF
[getpkt: discarding char 'ÿ']
Remote side has terminated connection.  GDBserver will reopen the connection.
Listening on port 1234

This happens if gdb times out waiting for gdbserver's ack,
and can be artificially created with this patch.
It fakes a timeout waiting for the ack of the command.

Index: remote.c
===================================================================
RCS file: /cvs/src/src/gdb/remote.c,v
retrieving revision 1.402
diff -u -p -r1.402 remote.c
--- remote.c	16 Apr 2010 07:49:35 -0000	1.402
+++ remote.c	25 Apr 2010 00:50:23 -0000
@@ -6490,6 +6490,9 @@ putpkt_binary (char *buf, int cnt)
   int i;
   unsigned char csum = 0;
   char *buf2 = alloca (cnt + 6);
+  int timeout_test = (rs->noack_mode == 0
+		      && strncmp (buf, "QStartNoAckMode",
+				  sizeof ("QStartNoAckMode")) != 0);
 
   int ch;
   int tcount = 0;
@@ -6554,7 +6557,15 @@ putpkt_binary (char *buf, int cnt)
 	 Handle any notification that arrives in the mean time.  */
       while (1)
 	{
-	  ch = readchar (remote_timeout);
+	  if (timeout_test)
+	    {
+	      ch = SERIAL_TIMEOUT;
+	      timeout_test = 0;
+	    }
+	  else
+	    {
+	      ch = readchar (remote_timeout);
+	    }
 
 	  if (remote_debug)
 	    {


The problem is if gdbserver is slow enough readchar can read in
both the original command and its resend, but gdbserver doesn't
use readchar to fetch the ack of its response packet.
So it will read the first command out of the buffer, ack it,
send the response, and wait for the ack from gdb.
gdb will eventually see the response, ack it, and continue.
But the resend of the command is still in the buffer,
so gdbserver processes it even though gdb has moved on to the next command.

So while gdb did:

send command1
timeout
resend command1
read ack
read reply
send ack
send command2
...

gdbserver will see:

read command1
read ack <<<---xxx
send response
read ack
read command1
...

and they become out of sync.

Anyways, a long explanation for a simple bug.
I've checked in the following fix.

There is another call to read() in input_interrupt.
I didn't touch that, at least not in this patch.
It *seems* like it will only get called when readchar's buffer is empty.

btw, after fixing this I found another bug: timeout handling in noack mode.
What happens if gdb times out waiting for the ack after sending
QStartNoAckMode?  gdb and gdbserver will again get out of sync.
I think the solution there is to either have no timeout in noack mode
or at least have a *much* longer timeout than the default of 2 seconds.


2010-04-26  Doug Evans  <dje@google.com>

	* remote-utils.c (putpkt_binary_1): Call readchar instead of read.
	Print received char after testing for error/eof instead of before.
	(input_interrupt): Tweak comment.

Index: remote-utils.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbserver/remote-utils.c,v
retrieving revision 1.73
diff -u -p -r1.73 remote-utils.c
--- remote-utils.c	17 Apr 2010 20:43:13 -0000	1.73
+++ remote-utils.c	26 Apr 2010 17:31:34 -0000
@@ -80,6 +80,8 @@ typedef int socklen_t;
 # define INVALID_DESCRIPTOR -1
 #endif
 
+static int readchar (void);
+
 /* A cache entry for a successfully looked-up symbol.  */
 struct sym_cache
 {
@@ -691,8 +693,8 @@ putpkt_binary_1 (char *buf, int cnt, int
   int i;
   unsigned char csum = 0;
   char *buf2;
-  char buf3[1];
   char *p;
+  int cc;
 
   buf2 = xmalloc (PBUFSIZ);
 
@@ -718,8 +720,6 @@ putpkt_binary_1 (char *buf, int cnt, int
 
   do
     {
-      int cc;
-
       if (write (remote_desc, buf2, p - buf2) != p - buf2)
 	{
 	  perror ("putpkt(write)");
@@ -746,29 +746,26 @@ putpkt_binary_1 (char *buf, int cnt, int
 	  fprintf (stderr, "putpkt (\"%s\"); [looking for ack]\n", buf2);
 	  fflush (stderr);
 	}
-      cc = read (remote_desc, buf3, 1);
-      if (remote_debug)
-	{
-	  fprintf (stderr, "[received '%c' (0x%x)]\n", buf3[0], buf3[0]);
-	  fflush (stderr);
-	}
 
-      if (cc <= 0)
-	{
-	  if (cc == 0)
-	    fprintf (stderr, "putpkt(read): Got EOF\n");
-	  else
-	    perror ("putpkt(read)");
+      cc = readchar ();
 
+      if (cc < 0)
+	{
 	  free (buf2);
 	  return -1;
 	}
 
+      if (remote_debug)
+	{
+	  fprintf (stderr, "[received '%c' (0x%x)]\n", cc, cc);
+	  fflush (stderr);
+	}
+
       /* Check for an input interrupt while we're here.  */
-      if (buf3[0] == '\003' && current_inferior != NULL)
+      if (cc == '\003' && current_inferior != NULL)
 	(*the_target->request_interrupt) ();
     }
-  while (buf3[0] != '+');
+  while (cc != '+');
 
   free (buf2);
   return 1;			/* Success! */
@@ -798,7 +795,8 @@ putpkt_notif (char *buf)
 
 /* Come here when we get an input interrupt from the remote side.  This
    interrupt should only be active while we are waiting for the child to do
-   something.  About the only thing that should come through is a ^C, which
+   something.  Thus this assumes readchar:bufcnt is 0.
+   About the only thing that should come through is a ^C, which
    will cause us to request child interruption.  */
 
 static void


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]