[win32] Fix suspend count handling
Pedro Alves
pedro_alves@portugalmail.pt
Wed Nov 21 00:35:00 GMT 2007
Hi,
This patch fixes a problem that was originally reported against
gdbserver/win32, which is also present on a native win32 debugger.
The gdbserver patch is here:
[gdbserver/win32] (3/11) Fix suspend count handling
http://sourceware.org/ml/gdb-patches/2007-11/msg00216.html
Let me re-describe the problem:
The current suspend_count handling breaks applications that use
SuspendThread on their own threads. The SuspendThread function
suspends a thread and returns its previous suspend count.
If a thread was already suspended by the debuggee, say, 3
times, gdb will do one SuspendThread call more (in thread_rec),
bringing the suspend_count to 4. Later, when the inferior
is being resumed, gdb will call ResumeThread suspend_count
times, in this case 4 times, which will leave a thread
running, while the debuggee wanted it to be suspended (with
a suspend count of 3).
This patch fixes it by turning the suspend_count counter
into a suspended flag that records if gdb itself has
suspended the thread. Gdb will then only call SuspendThread
on a thread if it hasn't already, and will only call Resume
thread if it has called SuspendThread itself.
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 reads "set breakpoint here", switch to the
other thread with "thread 2", effectivelly forcing a thread_rec
call, which calls SuspendThread, and sets suspend_count. Go back to
thread 1, and advance to the printf call. The suspend_count will be
0, instead of the expected 3.
I've asked this on the gdbserver mail, but let me re-ask it,
because I haven't done that work yet :-):
I have yet to turn this into a proper gdb test. Is that
wanted? Where shall I put it? gdb.base? gdb.thread? other?
No regressions on i686-pc-cygwin.
Cheers,
Pedro Alves
-------------- next part --------------
A non-text attachment was scrubbed...
Name: nat_suspend_count_fix.diff
Type: text/x-diff
Size: 2936 bytes
Desc: not available
URL: <http://sourceware.org/pipermail/gdb-patches/attachments/20071121/55b40369/attachment.bin>
More information about the Gdb-patches
mailing list