[Bug gdb/22992] GDB and Microsoft Windows thread pool

tromey at sourceware dot org sourceware-bugzilla@sourceware.org
Thu Oct 3 20:32:00 GMT 2019


https://sourceware.org/bugzilla/show_bug.cgi?id=22992

--- Comment #14 from Tom Tromey <tromey at sourceware dot org> ---
(In reply to Pedro Alves from comment #13)

> And supposedly, the breakpoint is NOT installed in the target at this point,
> right?  Or is it some other breakpoint?  Seems like it's the same from your
> logs.  If it is indeed the breakpoint that was removed, then that again
> suggests this is Windows returning the queued event.

As I understand it, gdb itself uninstalls the breakpoints before
single-stepping.
I did not actually verify this.

The only user breakpoint in my setup is the "dprintf" one (see the original
repro instructions in this bug).

> SuspendThread returns the thread's previous suspend count.  You could use
> that to check whether the program is unsuspending threads on its own.

Yes, I did this at some point.  In fact what I did is hack gdb to suspend
each thread 5 times, then also print out the suspension count after getting
a debug event.  All the relevant threads always reported their suspension
count as 5 -- which to my mind means it is unlikely that the inferior is doing
anything tricky.

> > I am thinking it might be ok to simply ignore such events.
> 
> Does Windows decrement the PC after a break automatically?  I forget.

There's no mention of this in windows-nat.c.  So I guess it defers to the arch?


I changed my gdb to (1) suspend threads when stepping (still seems like a big
oversight to me ... and despite what I said earlier, I'm not 100% sure that
gdbserver does this either), and (2) ignore spurious breakpoint events.

Now I get even weirder behavior:

Thread 4 received signal SIGSEGV, Segmentation fault.
[Switching to Thread 7664.0x32c8]
0x004015dc in (anonymous namespace)::Callback (context=0xe0) at sample.cxx:22
22        Sleep(100);  /* Do a "work". */

Look at that PC, then:

(gdb) disassemble
Dump of assembler code for function (anonymous
namespace)::Callback(TP_CALLBACK_INSTANCE*, void*, TP_WORK*):
   0x004015d0 <+0>:     push   %ebp
   0x004015d1 <+1>:     mov    %esp,%ebp
   0x004015d3 <+3>:     sub    $0x18,%esp
   0x004015d6 <+6>:     movl   $0x64,(%esp)
   0x004015dd <+13>:    mov    0x4091fc,%eax

... notice that it is in the middle of an instruction.


See comment #10 to see the results of the queueing experiment.  That stop is
suggestive
because it is one instruction past the location of the dprintf breakpoint.

1       dprintf        keep y   0x004015d6 in (anonymous
namespace)::Callback(TP_CALLBACK_INSTANCE*, void*, TP_WORK*) at sample.cxx:22

This seems to happen sometimes after one of these stops has been ignored, so I
somewhat suspect my patch, though I don't see anything obviously wrong in it.


Maybe the queueing approach is better and we should just live with the spurious
stop.
If the theory is that this is caused by internal event buffering in Windows,
then I
would definitely argue this direction.

-- 
You are receiving this mail because:
You are on the CC list for the bug.


More information about the Gdb-prs mailing list