public inbox for gdb@sourceware.org
 help / color / mirror / Atom feed
* Issue with multiple threads using remote protocol on riscv32
@ 2022-03-16 14:45 Denio, Mike
  2022-03-16 14:58 ` Pedro Alves
  0 siblings, 1 reply; 5+ messages in thread
From: Denio, Mike @ 2022-03-16 14:45 UTC (permalink / raw)
  To: gdb

I am seeing an issue with the remote protocol  on GDB with multiple threads on a riscv32 using the continue command. Not sure if it's a bug or just me, but it may be me as I am new to GDB.

I am using a custom server. The behavior is the same on both GDB 11.1 and 11.2.

This GDB was configured as follows:
   configure --host=x86_64-pc-linux-gnu --target=riscv32-unknown-elf
             --with-auto-load-dir=$debugdir:$datadir/auto-load
             --with-auto-load-safe-path=$debugdir:$datadir/auto-load
             --with-expat
             --with-gdb-datadir=/usr/local/share/gdb (relocatable)
             --with-jit-reader-dir=/usr/local/lib/gdb (relocatable)
             --without-libunwind-ia64
             --with-lzma
             --without-babeltrace
             --without-intel-pt
             --with-mpfr
             --without-xxhash
             --with-python=/usr
             --with-python-libdir=/usr/lib
             --without-debuginfod
             --without-guile
             --disable-source-highlight
             --with-separate-debug-dir=/usr/local/lib/debug (relocatable)

I am running in non-stop mode. A full log of the test is at the end of the email. The GDB commands I execute after connecting are:
(gdb) interrupt -a
(gdb) set *0x10000000=1
(gdb) c -a&

The problem is that the "c -a&" is implemented by a 'vCont;c:1' followed by a 'vCont;c', essentially telling thread 1 to continue twice, causing it to skip over a break.

Am I interpreting the commands incorrectly or am I sending GDB something incorrect that is confusing it?

Thanks,
Mike

---[ Remote Log ]------------------

'+'                     --->
'qSupported:multiprocess+;swbreak+;hwbreak+;qRelocInsn+;fork-events+;vfork-events+;exec-events+;vContSupported+;QThreadEvents+' --->
                        <--- '+$hwbreak+;vContSupported+;QStartNoAckMode+;QNonStop+;PacketSize=410#e3'
'+'                     --->
'vMustReplyEmpty'       --->
                        <--- '+$#00'
'+'                     --->
'QStartNoAckMode'       --->
                        <--- '+$OK#9a'
'+'                     --->
'!'                     --->
                        <--- '$OK#9a'
'Hg0'                   --->
                        <--- '$OK#9a'
'QNonStop:1'            --->
                        <--- '$OK#9a'
'qfThreadInfo'          --->
                        <--- '$m1,2#fc'
'qsThreadInfo'          --->
                        <--- '$l#6c'
'qAttached'             --->
                        <--- '$1#31'
'qTStatus'              --->
                        <--- '$#00'
'?'                     --->
                        <--- '$OK#9a'
'vCont?'                --->
                        <--- '$vCont;c;C;s;t#83'
'vCont;t:2'             --->
                        <--- '$OK#9a'
                        <--- '%Stop:T00thread:2;#b3'
'qSymbol::'             --->
                        <--- '$OK#9a'
'vStopped'              --->
                        <--- '$OK#9a'
'Hg2'                   --->
                        <--- '$OK#9a'
'g'                     --->
                        <--- '$000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000#80'
'qOffsets'              --->
                        <--- '$#00'
'qSymbol::'             --->
                        <--- '$OK#9a'
'vCont;c'               --->
                        <--- '$OK#9a'

(gdb) interrupt -a

'vCont;t'               --->
                        <--- '$OK#9a'
                        <--- '%Stop:T00thread:1;#b2'
'vStopped'              --->
                        <--- '$T00thread:2;#d3'
'vStopped'              --->
                        <--- '$OK#9a'
'Hg1'                   --->
                        <--- '$OK#9a'
'g'                     --->
                        <--- '$000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000#80'
'qfThreadInfo'          --->
                        <--- '$m1,2#fc'
'qsThreadInfo'          --->
                        <--- '$l#6c'
'Hg2'                   --->
                        <--- '$OK#9a'
'g'                     --->
                        <--- '$000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000#80'
'qfThreadInfo'          --->
                       <--- '$m1,2#fc'
'qsThreadInfo'          --->
                        <--- '$l#6c'

(gdb) set *0x10000000 = 1

'X10000000,0:'          --->
                        <--- '$#00'
'M10000000,4:01000000'  --->
                        <--- '$OK#9a'
'g'                     --->
                        <--- '$000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000#80'
'Hg1'                   --->
                        <--- '$OK#9a'
'g'                     --->
                        <--- '$000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000#80'

(gdb) c -a&

'vCont;c:1'             --->
                        <--- '$OK#9a'
                        <--- '%Stop:T05thread:1;#b7' // THIS STOP IS LOST BECAUSE GDB IMMEDIATELY TELLS THREAD 1 TO CONTINUE
'vCont;c'               --->
                        <--- '$OK#9a'
'vStopped'              --->
                        <--- '$OK#9a'
                        <--- '%Stop:T05thread:2;#b8'
'g'                     --->
                        <--- '$000000000000000000000000000000000000000000000000000000000000000000000000000000000002084000800041000200400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000#a5'
'qfThreadInfo'          --->
                        <--- '$m1,2#fc'
'qsThreadInfo'          --->
                        <--- '$l#6c'
'vStopped'              --->
                        <--- '$OK#9a'
'Hg2'                   --->
                        <--- '$OK#9a'
'g'                     --->
                        <--- '$000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000#80'
'qfThreadInfo'          --->
                        <--- '$m1,2#fc'
'qsThreadInfo'          --->
                        <--- '$l#6c'





^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Issue with multiple threads using remote protocol on riscv32
  2022-03-16 14:45 Issue with multiple threads using remote protocol on riscv32 Denio, Mike
@ 2022-03-16 14:58 ` Pedro Alves
  2022-03-16 15:10   ` [EXTERNAL] " Denio, Mike
  0 siblings, 1 reply; 5+ messages in thread
From: Pedro Alves @ 2022-03-16 14:58 UTC (permalink / raw)
  To: Denio, Mike, gdb

Hi!

On 2022-03-16 14:45, Denio, Mike via Gdb wrote:

> (gdb) c -a&
> 
> 'vCont;c:1'             --->
>                         <--- '$OK#9a'
>                         <--- '%Stop:T05thread:1;#b7' // THIS STOP IS LOST BECAUSE GDB IMMEDIATELY TELLS THREAD 1 TO CONTINUE

This stop hasn't been acknowledged yet with vStopped at this point, so ...

> 'vCont;c'               --->
>                         <--- '$OK#9a'

... from this 'vCont;c''s perspective, thread 1 is still running, so the server should ignore the 'c' action for thread 1.

gdbserver does this here, in linux-low.c::linux_set_resume_request

...
	  /* If the thread has a pending event that has already been
	     reported to GDBserver core, but GDB has not pulled the
	     event out of the vStopped queue yet, likewise, ignore the
	     (wildcard) resume request.  */
	  if (in_queued_stop_replies (thread->id))
	    {
	      threads_debug_printf
		("not resuming LWP %ld: has queued stop reply",
		 lwpid_of (thread));
	      continue;
	    }
...

Pedro Alves

^ permalink raw reply	[flat|nested] 5+ messages in thread

* RE: [EXTERNAL] Re: Issue with multiple threads using remote protocol on riscv32
  2022-03-16 14:58 ` Pedro Alves
@ 2022-03-16 15:10   ` Denio, Mike
  2022-03-17 17:52     ` Pedro Alves
  0 siblings, 1 reply; 5+ messages in thread
From: Denio, Mike @ 2022-03-16 15:10 UTC (permalink / raw)
  To: Pedro Alves, gdb

Ok, thanks. I'll have to think about how I'm going to implement that.

Is it safe to assume that this only affects the initial event, and that once I see the first  'vStopped', GDB will not interlace more 'vCont' commands?

For example, say I had 8 newly stopped threads such that GDB will end up calling 'vStopped' 8 times. Is it safe to assume that GDB will not send any new vCont in the middle of sending those 8 vStopped?

Thanks again,
Mike






^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [EXTERNAL] Re: Issue with multiple threads using remote protocol on riscv32
  2022-03-16 15:10   ` [EXTERNAL] " Denio, Mike
@ 2022-03-17 17:52     ` Pedro Alves
  2022-03-17 19:11       ` Denio, Mike
  0 siblings, 1 reply; 5+ messages in thread
From: Pedro Alves @ 2022-03-17 17:52 UTC (permalink / raw)
  To: Denio, Mike, gdb

On 2022-03-16 15:10, Denio, Mike wrote:
> Ok, thanks. I'll have to think about how I'm going to implement that.
> 
> Is it safe to assume that this only affects the initial event, and that once I see the first  'vStopped', GDB will not interlace more 'vCont' commands?
> 
> For example, say I had 8 newly stopped threads such that GDB will end up calling 'vStopped' 8 times. Is it safe to assume that GDB will not send any new vCont in the middle of sending those 8 vStopped?

Currently, when GDB issues a vStopped, it keeps issuing it until the remote side returns OK, indicating no more pending events.
But I wouldn't trust that that won't ever change.  Imagine at some point we come to the conclusion that it would be better to
batch fetching pending events, so that GDB went on to process the pending events once it fetches some N events out of vStopped,
maybe go on to process events out of some other remote connection / target, and then goes back to fetching another batch
of N events out of the first remote connection, and so forth.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* RE: [EXTERNAL] Re: Issue with multiple threads using remote protocol on riscv32
  2022-03-17 17:52     ` Pedro Alves
@ 2022-03-17 19:11       ` Denio, Mike
  0 siblings, 0 replies; 5+ messages in thread
From: Denio, Mike @ 2022-03-17 19:11 UTC (permalink / raw)
  To: Pedro Alves, gdb

I realized after I sent the second e-mail that I was overthinking the problem. I thought I was going to have to keep 2 states (a real state and a virtual state being what GDB thinks is the state), but then I realized this really only affects the vCont command, so I isolated the changes to that. I already tracked whether or not I was in an "event", so I wouldn't fire off a second "stop" while processing a previous "stop", and my vCont processing already filtered out threads from wildcards based on previous commands (for example: "s:2;c" would filter thread 2 from the continue). So I just added the bottom 2 lines to the "if" statement below and its working great.

                    if( "wildcard" )
                    {
                        // Wildcard sets all bits not previously set
                        tmask = m_AllMask;
                        tmask &= ~stop_mask;
                        tmask &= ~step_mask;
                        tmask &= ~cont_mask;
                        if( m_InEvent )
                            tmask &= ~m_EvtMask;
                    }

Basically, I adjust the vCont command before I even start executing it, which saved me from modifying the lower level debug processing. The "m_EvtMask" is updated on every "vStopped", so the scenario you outline in your e-mail should still work for me. The only thing that concerns me a bit with this simple approach is the signal numbers. I really don't understand them and have been using 00 for 't', 02 for '^c', and 05 for break point. But this seems problematic when processing is delayed. For example, I send a stop with 05 and then GDB sends a "vCont t" for the same thread. Obviously GDB must accept any signal for a "vCont t" because the stop may have already been sent.

Thanks again for the help.

I do have a small issue dealing with how I am using threads that I may send a separate e-mail about. Its not so much a functional issue as a limitation for which someone may be able to suggest a better solution.

Mike

-----Original Message-----
From: Pedro Alves <pedro@palves.net> 
Sent: Thursday, March 17, 2022 12:52 PM
To: Denio, Mike <miked@ti.com>; gdb@sourceware.org
Subject: Re: [EXTERNAL] Re: Issue with multiple threads using remote protocol on riscv32

On 2022-03-16 15:10, Denio, Mike wrote:
> Ok, thanks. I'll have to think about how I'm going to implement that.
> 
> Is it safe to assume that this only affects the initial event, and that once I see the first  'vStopped', GDB will not interlace more 'vCont' commands?
> 
> For example, say I had 8 newly stopped threads such that GDB will end up calling 'vStopped' 8 times. Is it safe to assume that GDB will not send any new vCont in the middle of sending those 8 vStopped?

Currently, when GDB issues a vStopped, it keeps issuing it until the remote side returns OK, indicating no more pending events.
But I wouldn't trust that that won't ever change.  Imagine at some point we come to the conclusion that it would be better to
batch fetching pending events, so that GDB went on to process the pending events once it fetches some N events out of vStopped,
maybe go on to process events out of some other remote connection / target, and then goes back to fetching another batch
of N events out of the first remote connection, and so forth.

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2022-03-17 19:11 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-03-16 14:45 Issue with multiple threads using remote protocol on riscv32 Denio, Mike
2022-03-16 14:58 ` Pedro Alves
2022-03-16 15:10   ` [EXTERNAL] " Denio, Mike
2022-03-17 17:52     ` Pedro Alves
2022-03-17 19:11       ` Denio, Mike

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).