> I don't see any race condition here. If gem5 has been told to wait, it  
> waits. If gdb has connected to it and hasn't told it to keep running, it  
> blocks.

But it doesn't work.  Try the following experiment: in the gdb source introduce 
a time-delay somewhere after connecting to the TCP port but before sending the 
very first bytes; for example like this:

diff --git a/gdb/remote.c b/gdb/remote.c
index 59075cb09f..60a5e80481 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -4562,6 +4562,8 @@ remote_target::start_remote (int from_tty, int extended_p)
   struct packet_config *noack_config;
   char *wait_status = NULL;
 
+usleep(3000000);
+
   /* Signal other parts that we're going through the initial setup,
      and so things may not be stable yet.  E.g., we don't try to
      install tracepoints until we've relocated symbols.  Also, a
...

Without the usleep, gem5 blocks.  With the usleep, gem5 doesn't block.
Just for fun I tried with GNU gdbserver and with Xilinx XMD just now, and both 
block in both cases.


-----"Gabe Black via gem5-dev" <[email protected]> wrote: -----
To: "gem5 Developer List" <[email protected]>
From: "Gabe Black via gem5-dev" <[email protected]>
Date: 08/07/2020 04:34AM
Cc: "Boris Shingarov" <[email protected]>, "Gabe Black" 
<[email protected]>
Subject: [gem5-dev] Re: Possible race condition (Remote GDB)

I think this code was originally written by Nate who is no longer with us. 
Looking at it, what I *think* it's doing starts in listen(). That sets up a 
poll queue event which listens for connection from gdb. When that gets 
triggered, that (slightly indirectly) calls connect which will check if 
somebody is already attached, and if not call the attach function. That will 
set up a poll queue event which waits for data to show up on the new 
connection. Once that happens, the incomingData method is called, and that sets 
up an event which will trigger at the next instruction boundary so that the 
remote GDB stub is operating synchronously with the rest of gem5 I think, and 
also so that it's not trying to look at state half way through an instruction. 
When that trap event fires, it calls the trap() method.

So at this point we know that there was a connect, we got sent data through it, 
and we're at an instruction boundary, if we're entering the debug loop because 
gdb connected to us.

If we're entering the gdb loop for some other reason (in the comment there it 
mentions the kernel's debug stub running in the guest triggering a breakpoint) 
then that's what I think that "if" is for. If we aren't active (because we 
didn't call attach() yet, ie no gdb has connected to us), then record that we 
are in fact active. If we were already active, ie gdb was already talking to 
us, tell it we got a trap and it can send us commands.

Regardless, then we try to read commands from gdb and execute them one by one. 
Getting commands is started by the recv(data) call in that function which 
eventually trickles down to a call to read() on the socket to retrieve a byte. 
If that blocks, then gdb hasn't told us what to do yet.

In the case where the CPU has been told to wait for GDB, gem5 just blocks after 
the GDB stub has been created until something connects to it.

I don't see any race condition here. If gem5 has been told to wait, it waits. 
If gdb has connected to it and hasn't told it to keep running, it blocks.

If, on the other hand, somebody throws a BadClient exception, for instance 
because the data from gdb is malformed, then gdb will be disconnected and the 
command loop will exit. This prevents a rogue connection or a misbehaving 
client from jamming up the gdb server and locking the simulation from 
progressing. The client can attempt to reattach to continue debugging which 
would act like a connection reboot, flushing away the broken connection and 
starting over. Also commands which return false tell the command loop to exit. 
This is how the continue command breaks out of the loop so the simulation can 
progress.

Gabe
On Thu, Aug 6, 2020 at 5:25 PM Boris Shingarov via gem5-dev <[email protected]> 
wrote:
It gets worse: I am beginning to suspect that this race is what ultimately 
causes the "xml for the wrong xlen" mystery (if the timing is unlucky, the CSPR 
isn't set yet).
 
 -----"Boris Shingarov via gem5-dev" <[email protected]> wrote: -----
 To: [email protected]
 From: "Boris Shingarov via gem5-dev" <[email protected]>
 Date: 08/06/2020 08:14PM
 Cc: "Boris Shingarov" <[email protected]>
 Subject: [gem5-dev] Possible race condition (Remote GDB)
 
 It looks to me that there is a race condition inherent in the design of 
DataEvent.
 The effect is that, even when CPU.wait_for_gdb attr is set and after the the 
RSP socket has connected, the relative timing of gdb's vs gem5's execution may 
or may not lead to gdb's presence being ignored.  It's like "hey gdb,I know you 
already connected, but if you aren't quick enough that the qSupported reaches 
the queue within N ms after connecting, I am going ahead without you; (and no I 
am not telling you what N is)".
 
 It looks like one fundamental issue here is the historical packet-oriented 
nature of RSP.  But it also looks like remote_gdb.cc:434,
 
 if (!active) {
     active = true;
 } else {
     // Tell remote host that an exception has occurred.
     send(csprintf("S%02x", type).c_str());
 }
 
 plays a central role.
 Can someone comment on how this is intended to work?  I must admit the comment 
above that code doesn't make sense to me.
 
 _______________________________________________
 gem5-dev mailing list -- [email protected]
 To unsubscribe send an email to [email protected]
 %(web_page_url)slistinfo%(cgiext)s/%(_internal_name)s
 _______________________________________________
 gem5-dev mailing list -- [email protected]
 To unsubscribe send an email to [email protected]
 %(web_page_url)slistinfo%(cgiext)s/%(_internal_name)s
  
_______________________________________________
gem5-dev mailing list -- [email protected]
To unsubscribe send an email to [email protected]
%(web_page_url)slistinfo%(cgiext)s/%(_internal_name)s
_______________________________________________
gem5-dev mailing list -- [email protected]
To unsubscribe send an email to [email protected]
%(web_page_url)slistinfo%(cgiext)s/%(_internal_name)s

Reply via email to