[gdbserver/win32] (3/11) Fix suspend count handling

Pedro Alves pedro_alves@portugalmail.pt
Mon Nov 12 02:07:00 GMT 2007


Hi,

As Leo reported earlier, the suspend_count handling breaks
applications that use SuspendThread on their own threads.
SuspendThread returns the previous suspend count of the
thread, and gdbserver is calling ResumeThread that many times.
If the Thread was already suspended, say, 3 times, gdbserver will
do one SuspendThread call (in thread_rec), and 4 ResumeThread
calls when resuming.

This patch fixes it by turning the suspend_count counter into
a suspended flag.

Here is a test that shows the problem:

     >cat ~/suspendfix/main.c
#include <windows.h>

HANDLE started;
HANDLE stop;

DWORD WINAPI
thread_start (void *arg)
{
       SetEvent (started);
       WaitForSingleObject (stop, INFINITE);
       return 0;
}

int
main (int argc, char **argv)
{
       int i;
       DWORD suspend_count;
       started = CreateEvent (NULL, TRUE, FALSE, NULL);
       stop = CreateEvent (NULL, TRUE, FALSE, NULL);

       HANDLE h = CreateThread (NULL, 0, thread_start, NULL,
                                0, NULL);

       WaitForSingleObject (started, INFINITE);

       for (i = 0; i < 3; i++)
         if (SuspendThread (h) == (DWORD) -1)
           {
             printf ("SuspendThreadFailed\n");
             return 1;
           }

       suspend_count = ResumeThread (h); /* set breakpoint here */

       printf ("%lu\n", suspend_count); /* should be 3 */

       while ((suspend_count = ResumeThread (h)) != 0
              && suspend_count != -1)
         ;
       SetEvent (stop);
       WaitForSingleObject (h, INFINITE);
       CloseHandle (h);
       CloseHandle (started);
       CloseHandle (stop);
       return 0;
}

Set a breakpoint where it read "set breakpoint here", switch to the
other thread with "thread 2", effectivelly forcing a thread_rec
call, which calls SuspendThread, and sets suspend_count.  Since the
win32 support can't resume with a different thread, so go back to
thread 1, and step.  The suspend_count will be 0, instead of 3.

I have yet to turn this into a proper gdb test.  Is that wanted?  Where
shall I put it?  gdb.base?  gdb.thread?  other?

Note: The native (gdb/win32-nat.c) support also has the same bug.

Regtested on a local i686-pc-cygwin gdbserver, and against
a arm-wince remote.

Cheers,
Pedro Alves



-------------- next part --------------
A non-text attachment was scrubbed...
Name: suspend_count_fix.diff
Type: text/x-diff
Size: 3163 bytes
Desc: not available
URL: <http://sourceware.org/pipermail/gdb-patches/attachments/20071112/b8115977/attachment.bin>


More information about the Gdb-patches mailing list