Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* [win32] Fix suspend count handling
@ 2007-11-21  0:35 Pedro Alves
  2007-11-21 11:25 ` Pierre Muller
  0 siblings, 1 reply; 28+ messages in thread
From: Pedro Alves @ 2007-11-21  0:35 UTC (permalink / raw)
  To: gdb-patches

[-- Attachment #1: Type: text/plain, Size: 2945 bytes --]

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




[-- Attachment #2: nat_suspend_count_fix.diff --]
[-- Type: text/x-diff, Size: 2936 bytes --]

2007-11-21  Pedro Alves  <pedro_alves@portugalmail.pt>

	* win32-nat.c (thread_info_struct): Rename suspend_count to
	suspended, to be used as a flag.
	(thread_rec): Only suspend the thread if it wasn't suspended by
	gdb before.  Warn if suspending failed.
	(win32_continue): Update usage of the `suspended' flag.

---
 gdb/win32-nat.c |   33 +++++++++++++++++++++------------
 1 file changed, 21 insertions(+), 12 deletions(-)

Index: src/gdb/win32-nat.c
===================================================================
--- src.orig/gdb/win32-nat.c	2007-11-11 23:13:04.000000000 +0000
+++ src/gdb/win32-nat.c	2007-11-12 22:35:26.000000000 +0000
@@ -112,14 +112,14 @@ static enum target_signal last_sig = TAR
 /* Set if a signal was received from the debugged process */
 
 /* Thread information structure used to track information that is
-   not available in gdb's thread structure. */
+   not available in gdb's thread structure.  */
 typedef struct thread_info_struct
   {
     struct thread_info_struct *next;
     DWORD id;
     HANDLE h;
     char *name;
-    int suspend_count;
+    int suspended;
     int reload_context;
     CONTEXT context;
     STACKFRAME sf;
@@ -244,9 +244,10 @@ check (BOOL ok, const char *file, int li
 		     GetLastError ());
 }
 
-/* Find a thread record given a thread id.
-   If get_context then also retrieve the context for this
-   thread. */
+/* Find a thread record given a thread id passed in ID.  If
+   GET_CONTEXT is not 0, then also retrieve the context for this
+   thread.  If GET_CONTEXT is negative, then don't suspend the
+   thread.  */
 static thread_info *
 thread_rec (DWORD id, int get_context)
 {
@@ -255,12 +256,21 @@ thread_rec (DWORD id, int get_context)
   for (th = &thread_head; (th = th->next) != NULL;)
     if (th->id == id)
       {
-	if (!th->suspend_count && get_context)
+	if (!th->suspended && get_context)
 	  {
 	    if (get_context > 0 && id != current_event.dwThreadId)
-	      th->suspend_count = SuspendThread (th->h) + 1;
+	      {
+		if (SuspendThread (th->h) == (DWORD) -1)
+		  {
+		    DWORD err = GetLastError ();
+		    warning (_("SuspendThread failed. (winerr %d)"),
+			     (int) err);
+		    return NULL;
+		  }
+		th->suspended = 1;
+	      }
 	    else if (get_context < 0)
-	      th->suspend_count = -1;
+	      th->suspended = -1;
 	    th->reload_context = 1;
 	  }
 	return th;
@@ -1127,12 +1137,11 @@ win32_continue (DWORD continue_status, i
 			    continue_status);
   if (res)
     for (th = &thread_head; (th = th->next) != NULL;)
-      if (((id == -1) || (id == (int) th->id)) && th->suspend_count)
+      if (((id == -1) || (id == (int) th->id)) && th->suspended)
 	{
-
-	  for (i = 0; i < th->suspend_count; i++)
+	  if (th->suspended > 0)
 	    (void) ResumeThread (th->h);
-	  th->suspend_count = 0;
+	  th->suspended = 0;
 	  if (debug_registers_changed)
 	    {
 	      /* Only change the value of the debug registers */


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

* RE: [win32] Fix suspend count handling
  2007-11-21  0:35 [win32] Fix suspend count handling Pedro Alves
@ 2007-11-21 11:25 ` Pierre Muller
  2007-11-21 13:43   ` Pedro Alves
  0 siblings, 1 reply; 28+ messages in thread
From: Pierre Muller @ 2007-11-21 11:25 UTC (permalink / raw)
  To: 'Pedro Alves', gdb-patches

  Hi Pedro,

  I agree with you that the ResumeThread should be called
only once, even if the suspend_count is > 1, but when I tested your test
application,
I obtained 4 as a result with the current gdb head.
  This is because in fact the thread suspend_count are
only restored after ContinueDebugEvent is called.
  Thus the debugged event can possibly called 
ResumeThread before gdb does so, thus obtaining a
Thread count of 4 instead of 0...
  The first answer that comes to mind would be to
called ResumeThread before calling ContinueDebugEvent,
but that would mean that other threads would be restarted before
the thread that caused the debug event, which is
probably also not good.

  I would propose to do it this way:
  -for threads that where already suspended, and for which gdb
increased the suspend count, we should restore the suspend count before
calling ContinueDebugEvent, while for the thread that were
not suspended before, we should resume them after the call
to ContinueDebugEvent.
  This means that we should keep the suspend_count variable as an int
and loop once before ContinueDebugEvent call (restoring
the suspend count of debuggee suspended threads,
identified by the fact that their suspend_count is > 1,
calling ResumeThread only once, as you suggest in your patch), and
loop again after the call to resume all other threads that
were running at the time of the debug event (those which
have a suspend_count of 1).

Pierre

> -----Original Message-----
> From: gdb-patches-owner@sourceware.org [mailto:gdb-patches-
> owner@sourceware.org] On Behalf Of Pedro Alves
> Sent: Wednesday, November 21, 2007 1:35 AM
> To: gdb-patches@sourceware.org
> Subject: [win32] Fix suspend count handling
> 
> 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
> 
> 




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

* Re: [win32] Fix suspend count handling
  2007-11-21 11:25 ` Pierre Muller
@ 2007-11-21 13:43   ` Pedro Alves
  2007-11-21 14:13     ` Pierre Muller
  0 siblings, 1 reply; 28+ messages in thread
From: Pedro Alves @ 2007-11-21 13:43 UTC (permalink / raw)
  To: gdb-patches; +Cc: Pierre Muller

On Nov 21, 2007 11:25 AM, Pierre Muller wrote:
>   Hi Pedro,
>
>   I agree with you that the ResumeThread should be called
> only once, even if the suspend_count is > 1, but when I tested your test
> application,
> I obtained 4 as a result with the current gdb head.
>   This is because in fact the thread suspend_count are
> only restored after ContinueDebugEvent is called.

I suspect you didn't reproduce the exact steps I described, probably
because I didn't describe it sufficiently.  Here's a test run:

$ gdb/gdb.exe main.exe
GNU gdb 6.7.50.20071121
Copyright (C) 2007 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i686-pc-cygwin"...
(gdb) list 37
32              printf ("SuspendThreadFailed\n");
33              return 1;
34            }
35
36
37        suspend_count = ResumeThread (h); /* set breakpoint here */
38
39        printf ("%lu\n", suspend_count); /* should be 3 */
40
41        while ((suspend_count = ResumeThread (h)) != 0
(gdb) b 37
Breakpoint 1 at 0x40119a: file main.c, line 37.
(gdb) r
Starting program: /d/gdb/build/main.exe

Breakpoint 1, main (argc=1, argv=0x6b3270) at main.c:37
37        suspend_count = ResumeThread (h); /* set breakpoint here */
(gdb) info threads
  3 thread 11344.0x2e54  0x7c90eb94 in ntdll!LdrAccessResource () from
/cygdrive/c/WINNT/system32/ntdll.dll
  2 thread 11344.0x1e4c  0x7c90eb94 in ntdll!LdrAccessResource () from
/cygdrive/c/WINNT/system32/ntdll.dll
* 1 thread 11344.0x2d00  main (argc=1, argv=0x6b3270) at main.c:37
(gdb) thread 3
[Switching to thread 3 (thread 11344.0x2e54)]#0  0x7c90eb94 in
ntdll!LdrAccessResource ()
   from /cygdrive/c/WINNT/system32/ntdll.dll
(gdb) thread 1
[Switching to thread 1 (thread 11344.0x2d00)]#0  main (argc=1,
argv=0x6b3270) at main.c:37
37        suspend_count = ResumeThread (h); /* set breakpoint here */
(gdb) n
39        printf ("%lu\n", suspend_count); /* should be 3 */
(gdb) p suspend_count
$1 = 0
(gdb)

You must switch to the suspended thread for gdb to call SuspendThread
on it, otherwise, gdb will not try to ResumeThread it, and the bug isn't
triggered.  I mentioned "thread 2" in the other mail, but as seen on
the "info threads" result, the gdb tid of the suspended thread will vary.
A proper testcase would switch to all threads one by one and then
back to thread 1 to ensure the bug is triggered.

>   Thus the debugged event can possibly called
> ResumeThread before gdb does so, thus obtaining a
> Thread count of 4 instead of 0...
>   The first answer that comes to mind would be to
> called ResumeThread before calling ContinueDebugEvent,
> but that would mean that other threads would be restarted before
> the thread that caused the debug event, which is
> probably also not good.
>

Not true.  See here:
  [The Win32 Debugging Application Programming Interface]
  http://msdn2.microsoft.com/en-us/library/ms809754.aspx

  "When a debug event occurs, execution of that process is suspended until
  the debugger calls the ContinueDebugEvent function. Consequently,
all threads in
  the process are suspended while the debugger is processing the debug event."

In fact my patch at:
 [win32] Fix watchpoint support
 http://sourceware.org/ml/gdb-patches/2007-11/msg00390.html

... ensures that ContinueDebugEvent is always called last.

Cheers,
Pedro Alves


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

* RE: [win32] Fix suspend count handling
  2007-11-21 13:43   ` Pedro Alves
@ 2007-11-21 14:13     ` Pierre Muller
  2007-11-21 15:08       ` Pedro Alves
  0 siblings, 1 reply; 28+ messages in thread
From: Pierre Muller @ 2007-11-21 14:13 UTC (permalink / raw)
  To: 'Pedro Alves', gdb-patches



> -----Original Message-----
> From: alves.ped@gmail.com [mailto:alves.ped@gmail.com] On Behalf Of
> Pedro Alves
> Sent: Wednesday, November 21, 2007 2:43 PM
> To: gdb-patches@sourceware.org
> Cc: Pierre Muller
> Subject: Re: [win32] Fix suspend count handling
> 
> On Nov 21, 2007 11:25 AM, Pierre Muller wrote:
> >   Hi Pedro,
> >
> >   I agree with you that the ResumeThread should be called
> > only once, even if the suspend_count is > 1, but when I tested your
> test
> > application,
> > I obtained 4 as a result with the current gdb head.
> >   This is because in fact the thread suspend_count are
> > only restored after ContinueDebugEvent is called.
> 
> I suspect you didn't reproduce the exact steps I described, probably
> because I didn't describe it sufficiently.  Here's a test run:
  You are right indeed (see below) 
> $ gdb/gdb.exe main.exe
> GNU gdb 6.7.50.20071121
> Copyright (C) 2007 Free Software Foundation, Inc.
> License GPLv3+: GNU GPL version 3 or later
> <http://gnu.org/licenses/gpl.html>
> This is free software: you are free to change and redistribute it.
> There is NO WARRANTY, to the extent permitted by law.  Type "show
> copying"
> and "show warranty" for details.
> This GDB was configured as "i686-pc-cygwin"...
> (gdb) list 37
> 32              printf ("SuspendThreadFailed\n");
> 33              return 1;
> 34            }
> 35
> 36
> 37        suspend_count = ResumeThread (h); /* set breakpoint here */
> 38
> 39        printf ("%lu\n", suspend_count); /* should be 3 */
> 40
> 41        while ((suspend_count = ResumeThread (h)) != 0
> (gdb) b 37
> Breakpoint 1 at 0x40119a: file main.c, line 37.
> (gdb) r
> Starting program: /d/gdb/build/main.exe
> 
> Breakpoint 1, main (argc=1, argv=0x6b3270) at main.c:37
> 37        suspend_count = ResumeThread (h); /* set breakpoint here */
> (gdb) info threads
>   3 thread 11344.0x2e54  0x7c90eb94 in ntdll!LdrAccessResource () from
> /cygdrive/c/WINNT/system32/ntdll.dll
>   2 thread 11344.0x1e4c  0x7c90eb94 in ntdll!LdrAccessResource () from
> /cygdrive/c/WINNT/system32/ntdll.dll
> * 1 thread 11344.0x2d00  main (argc=1, argv=0x6b3270) at main.c:37

  This comes from the fact that cygwin startup code generated a thread
dedicated to signal handling,
but I figures that out after a while, while testing your patch...
> (gdb) thread 3
> [Switching to thread 3 (thread 11344.0x2e54)]#0  0x7c90eb94 in
> ntdll!LdrAccessResource ()
>    from /cygdrive/c/WINNT/system32/ntdll.dll
> (gdb) thread 1
> [Switching to thread 1 (thread 11344.0x2d00)]#0  main (argc=1,
> argv=0x6b3270) at main.c:37
> 37        suspend_count = ResumeThread (h); /* set breakpoint here */
> (gdb) n
> 39        printf ("%lu\n", suspend_count); /* should be 3 */
> (gdb) p suspend_count
> $1 = 0
> (gdb)

  Your patch does indeed correct this to 3, which is what is wanted.
But if you use 'continue' instead of 'next' when you are at line
37, you will get '4' printed out instead of three, because
the main thread will have call SuspendThread before gdb does.
This is at least what happens on my computer.

> 
> You must switch to the suspended thread for gdb to call SuspendThread
> on it, otherwise, gdb will not try to ResumeThread it, and the bug
> isn't
> triggered.  I mentioned "thread 2" in the other mail, but as seen on
> the "info threads" result, the gdb tid of the suspended thread will
> vary.
> A proper testcase would switch to all threads one by one and then
> back to thread 1 to ensure the bug is triggered.
> 
> >   Thus the debugged event can possibly called
> > ResumeThread before gdb does so, thus obtaining a
> > Thread count of 4 instead of 0...
> >   The first answer that comes to mind would be to
> > called ResumeThread before calling ContinueDebugEvent,
> > but that would mean that other threads would be restarted before
> > the thread that caused the debug event, which is
> > probably also not good.
> >
> 
> Not true.  See here:
>   [The Win32 Debugging Application Programming Interface]
>   http://msdn2.microsoft.com/en-us/library/ms809754.aspx
> 
>   "When a debug event occurs, execution of that process is suspended
> until
>   the debugger calls the ContinueDebugEvent function. Consequently,
> all threads in
>   the process are suspended while the debugger is processing the debug
> event."
> 
> In fact my patch at:
>  [win32] Fix watchpoint support
>  http://sourceware.org/ml/gdb-patches/2007-11/msg00390.html
> 
> ... ensures that ContinueDebugEvent is always called last.

  OK, in that case it is indeed correct to do all the ResumeThread calls
before ContinueDebugEvent is called, and thus the suspend_count can be
replaced
by suspended Boolean value.
  But only the combination of the two patches will ensure to 
always obtain '3' using 'continue' or 'next'.


Pierre




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

* Re: [win32] Fix suspend count handling
  2007-11-21 14:13     ` Pierre Muller
@ 2007-11-21 15:08       ` Pedro Alves
  2007-11-21 15:32         ` Pierre Muller
  2007-11-21 18:19         ` Pedro Alves
  0 siblings, 2 replies; 28+ messages in thread
From: Pedro Alves @ 2007-11-21 15:08 UTC (permalink / raw)
  To: Pierre Muller; +Cc: gdb-patches

On Nov 21, 2007 2:13 PM, Pierre Muller wrote:

>   Your patch does indeed correct this to 3, which is what is wanted.
> But if you use 'continue' instead of 'next' when you are at line
> 37, you will get '4' printed out instead of three, because
> the main thread will have call SuspendThread before gdb does.
> This is at least what happens on my computer.
>

Are you sure this was from a gdb with this patch installed?  I get 4
without the patch, but with this patch (*without* the other
watchpoint patch on top) I still get 3 no matter how I try it:

$ gdb/gdb.exe main.exe
GNU gdb 6.7.50.20071121
Copyright (C) 2007 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i686-pc-cygwin"...
(gdb) b 37
Breakpoint 1 at 0x40119a: file main.c, line 37.
(gdb) r
Starting program: /d/gdb/build/main.exe

Breakpoint 1, main (argc=1, argv=0x6b3270) at main.c:37
37        suspend_count = ResumeThread (h); /* set breakpoint here */
(gdb) c
Continuing.
3

Program exited normally.
(gdb)

>
>   OK, in that case it is indeed correct to do all the ResumeThread calls
> before ContinueDebugEvent is called, and thus the suspend_count can be
> replaced
> by suspended Boolean value.

Not a boolean, its a three state -- suspend_count also accepted -1, and I've
kept that.

>   But only the combination of the two patches will ensure to
> always obtain '3' using 'continue' or 'next'.

That's not what I see here.  Can you show me a run where you get 4
only this patch applied?

Cheers,
Pedro Alves


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

* RE: [win32] Fix suspend count handling
  2007-11-21 15:08       ` Pedro Alves
@ 2007-11-21 15:32         ` Pierre Muller
  2007-11-21 18:19         ` Pedro Alves
  1 sibling, 0 replies; 28+ messages in thread
From: Pierre Muller @ 2007-11-21 15:32 UTC (permalink / raw)
  To: 'Pedro Alves'; +Cc: gdb-patches



> -----Original Message-----
> From: gdb-patches-owner@sourceware.org [mailto:gdb-patches-
> owner@sourceware.org] On Behalf Of Pedro Alves
> Sent: Wednesday, November 21, 2007 4:08 PM
> To: Pierre Muller
> Cc: gdb-patches@sourceware.org
> Subject: Re: [win32] Fix suspend count handling
> 
> On Nov 21, 2007 2:13 PM, Pierre Muller wrote:
> 
> >   Your patch does indeed correct this to 3, which is what is wanted.
> > But if you use 'continue' instead of 'next' when you are at line
> > 37, you will get '4' printed out instead of three, because
> > the main thread will have call SuspendThread before gdb does.
> > This is at least what happens on my computer.
> >
> 
> Are you sure this was from a gdb with this patch installed?  I get 4
> without the patch, but with this patch (*without* the other
> watchpoint patch on top) I still get 3 no matter how I try it:
> 
> $ gdb/gdb.exe main.exe
> GNU gdb 6.7.50.20071121
> Copyright (C) 2007 Free Software Foundation, Inc.
> License GPLv3+: GNU GPL version 3 or later
> <http://gnu.org/licenses/gpl.html>
> This is free software: you are free to change and redistribute it.
> There is NO WARRANTY, to the extent permitted by law.  Type "show
> copying"
> and "show warranty" for details.
> This GDB was configured as "i686-pc-cygwin"...
> (gdb) b 37
> Breakpoint 1 at 0x40119a: file main.c, line 37.
> (gdb) r
> Starting program: /d/gdb/build/main.exe
> 
> Breakpoint 1, main (argc=1, argv=0x6b3270) at main.c:37
> 37        suspend_count = ResumeThread (h); /* set breakpoint here */
> (gdb) c
> Continuing.
> 3
  You need to switch to the thread that is suspended to get '4' as a result,
otherwise you get '3'.

> Program exited normally.
> (gdb)
> 
> >
> >   OK, in that case it is indeed correct to do all the ResumeThread
> calls
> > before ContinueDebugEvent is called, and thus the suspend_count can
> be
> > replaced
> > by suspended Boolean value.
> 
> Not a boolean, its a three state -- suspend_count also accepted -1, and
> I've
> kept that.
> 
> >   But only the combination of the two patches will ensure to
> > always obtain '3' using 'continue' or 'next'.
> 
> That's not what I see here.  Can you show me a run where you get 4
> only this patch applied?
Just add a 'thread 3' after the breakpoint is trigged and 'continue'.

Pierre




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

* Re: [win32] Fix suspend count handling
  2007-11-21 15:08       ` Pedro Alves
  2007-11-21 15:32         ` Pierre Muller
@ 2007-11-21 18:19         ` Pedro Alves
  2007-11-21 23:33           ` Pedro Alves
  1 sibling, 1 reply; 28+ messages in thread
From: Pedro Alves @ 2007-11-21 18:19 UTC (permalink / raw)
  To: Pierre Muller; +Cc: gdb-patches

Pedro Alves wrote:
> On Nov 21, 2007 2:13 PM, Pierre Muller wrote:
> That's not what I see here.  Can you show me a run where you get 4
> only this patch applied?
>

I did try that, but posted a log of not doing it :-).

I've just tried about 30 times, and only once I did see
a 4 coming out ...  oh, well, one of those things.

Since the watchpoint patch should fix this, what shall I do?  Shall I merge
the two and resubmit, or leave it at that ?  They've already been tested
together without regressions.

-- 
Pedro Alves


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

* Re: [win32] Fix suspend count handling
  2007-11-21 18:19         ` Pedro Alves
@ 2007-11-21 23:33           ` Pedro Alves
  2007-11-22  9:19             ` Pierre Muller
  2007-11-23  1:07             ` Christopher Faylor
  0 siblings, 2 replies; 28+ messages in thread
From: Pedro Alves @ 2007-11-21 23:33 UTC (permalink / raw)
  To: Pierre Muller; +Cc: gdb-patches

[-- Attachment #1: Type: text/plain, Size: 3620 bytes --]

Pedro Alves wrote:
> Pedro Alves wrote:
>> On Nov 21, 2007 2:13 PM, Pierre Muller wrote:
>> That's not what I see here.  Can you show me a run where you get 4
>> only this patch applied?
>>
> 
> I did try that, but posted a log of not doing it :-).
> 
> I've just tried about 30 times, and only once I did see
> a 4 coming out ...  oh, well, one of those things.
> 

OK.  Back at my home laptop, I can reproduce that with
no problems.  Let me clarify what the 4 problem really is.
It's a race between gdb and the inferior.

Take this slightly changed test case.  The only difference
to the original version is the extra Sleep call.

#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;
         }

     Sleep (300);

     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;
}

If you do the "break at ...", "run", "thread 3", "continue"
sequence, and "..." is the "Sleep" line, you'll get 3,
but if you put the break at the /* set breakpoint here */
line, you'll get 4 (if you're (un)lucky).

The race happens due to the fact that gdb is
doing something similar to this:

win32_continue()
{
    ContinueDebugEvent (...);  /* Resumes all non suspended
                                  threads of the process.  */

    /* At this point, gdb is running concurrently with
       the inferior threads that were not suspended - which
       included the main thread of the testcase.  */
    foreach t in threads do
       if t is suspended
          ResumeThread t
       fi
    done
}

If you break at the Sleep call, when we resume, gdb will
have a bit of time to call ResumeThread on the suspended
thread of the testcase.  If you instead break at the
ResumeThread line, you'll have a good chance that the
inferior wins the race, hence the "4" result (remember
that ResumeThread returns the previous suspend count).
If we put something like this after the ResumeThread call:

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

+  Sleep (300);
+  SuspendThread (h);
+  suspend_count = ResumeThread (h);

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

... you'll see that eventually gdb will bring the
suspend count back to 3.  (A SuspendThread, ResumeThread
pair is the way to get at the suspend count.)

> Since the watchpoint patch should fix this, what shall I do?  Shall I merge
> the two and resubmit, or leave it at that ?  They've already been tested
> together without regressions.
> 

Here is the merge from the patch I posted at the start of the
thread with this patch:
    [win32] Fix watchpoint support
    http://sourceware.org/ml/gdb-patches/2007-11/msg00390.html

This patch fixes both the suspend_count
handling, and the watchpoint support.

Thanks Pierre, for looking at it.

OK ?

-- 
Pedro Alves

[-- Attachment #2: suspend_count_fix_plus_watchpoints.diff --]
[-- Type: text/x-diff, Size: 5177 bytes --]

2007-11-21  Pedro Alves  <pedro_alves@portugalmail.pt>

	* win32-nat.c (thread_info_struct): Rename suspend_count to
	suspended, to be used as a flag.
	(thread_rec): Only suspend the thread if it wasn't suspended by
	gdb before.  Warn if suspending failed.
	(win32_add_thread): Set Dr6 to 0xffff0ff0.
	(win32_resume): Likewise.
	(win32_continue): Set Dr6 to 0xffff0ff0.  Update usage of the
	`suspended' flag.  Do ContinueDebugEvent after resuming the
	suspended threads, not before.  Set threads' contexts before
	resuming them, not after.

---
 gdb/win32-nat.c |   80 +++++++++++++++++++++++++++++++-------------------------
 1 file changed, 45 insertions(+), 35 deletions(-)

Index: src/gdb/win32-nat.c
===================================================================
--- src.orig/gdb/win32-nat.c	2007-11-11 23:13:04.000000000 +0000
+++ src/gdb/win32-nat.c	2007-11-21 22:39:56.000000000 +0000
@@ -112,14 +112,14 @@ static enum target_signal last_sig = TAR
 /* Set if a signal was received from the debugged process */
 
 /* Thread information structure used to track information that is
-   not available in gdb's thread structure. */
+   not available in gdb's thread structure.  */
 typedef struct thread_info_struct
   {
     struct thread_info_struct *next;
     DWORD id;
     HANDLE h;
     char *name;
-    int suspend_count;
+    int suspended;
     int reload_context;
     CONTEXT context;
     STACKFRAME sf;
@@ -244,9 +244,10 @@ check (BOOL ok, const char *file, int li
 		     GetLastError ());
 }
 
-/* Find a thread record given a thread id.
-   If get_context then also retrieve the context for this
-   thread. */
+/* Find a thread record given a thread id passed in ID.  If
+   GET_CONTEXT is not 0, then also retrieve the context for this
+   thread.  If GET_CONTEXT is negative, then don't suspend the
+   thread.  */
 static thread_info *
 thread_rec (DWORD id, int get_context)
 {
@@ -255,12 +256,21 @@ thread_rec (DWORD id, int get_context)
   for (th = &thread_head; (th = th->next) != NULL;)
     if (th->id == id)
       {
-	if (!th->suspend_count && get_context)
+	if (!th->suspended && get_context)
 	  {
 	    if (get_context > 0 && id != current_event.dwThreadId)
-	      th->suspend_count = SuspendThread (th->h) + 1;
+	      {
+		if (SuspendThread (th->h) == (DWORD) -1)
+		  {
+		    DWORD err = GetLastError ();
+		    warning (_("SuspendThread failed. (winerr %d)"),
+			     (int) err);
+		    return NULL;
+		  }
+		th->suspended = 1;
+	      }
 	    else if (get_context < 0)
-	      th->suspend_count = -1;
+	      th->suspended = -1;
 	    th->reload_context = 1;
 	  }
 	return th;
@@ -294,8 +304,7 @@ win32_add_thread (DWORD id, HANDLE h)
       th->context.Dr1 = dr[1];
       th->context.Dr2 = dr[2];
       th->context.Dr3 = dr[3];
-      /* th->context.Dr6 = dr[6];
-      FIXME: should we set dr6 also ?? */
+      th->context.Dr6 = 0xffff0ff0;
       th->context.Dr7 = dr[7];
       CHECK (SetThreadContext (th->h, &th->context));
       th->context.ContextFlags = 0;
@@ -1122,32 +1131,34 @@ win32_continue (DWORD continue_status, i
 		  current_event.dwProcessId, current_event.dwThreadId,
 		  continue_status == DBG_CONTINUE ?
 		  "DBG_CONTINUE" : "DBG_EXCEPTION_NOT_HANDLED"));
+
+  for (th = &thread_head; (th = th->next) != NULL;)
+    if ((id == -1 || id == (int) th->id)
+	&& th->suspended)
+      {
+	if (debug_registers_changed)
+	  {
+	    th->context.ContextFlags |= CONTEXT_DEBUG_REGISTERS;
+	    th->context.Dr0 = dr[0];
+	    th->context.Dr1 = dr[1];
+	    th->context.Dr2 = dr[2];
+	    th->context.Dr3 = dr[3];
+	    th->context.Dr6 = 0xffff0ff0;
+	    th->context.Dr7 = dr[7];
+	  }
+	if (th->context.ContextFlags)
+	  {
+	    CHECK (SetThreadContext (th->h, &th->context));
+	    th->context.ContextFlags = 0;
+	  }
+	if (th->suspended > 0)
+	  (void) ResumeThread (th->h);
+	th->suspended = 0;
+      }
+
   res = ContinueDebugEvent (current_event.dwProcessId,
 			    current_event.dwThreadId,
 			    continue_status);
-  if (res)
-    for (th = &thread_head; (th = th->next) != NULL;)
-      if (((id == -1) || (id == (int) th->id)) && th->suspend_count)
-	{
-
-	  for (i = 0; i < th->suspend_count; i++)
-	    (void) ResumeThread (th->h);
-	  th->suspend_count = 0;
-	  if (debug_registers_changed)
-	    {
-	      /* Only change the value of the debug registers */
-	      th->context.ContextFlags = CONTEXT_DEBUG_REGISTERS;
-	      th->context.Dr0 = dr[0];
-	      th->context.Dr1 = dr[1];
-	      th->context.Dr2 = dr[2];
-	      th->context.Dr3 = dr[3];
-	      /* th->context.Dr6 = dr[6];
-		 FIXME: should we set dr6 also ?? */
-	      th->context.Dr7 = dr[7];
-	      CHECK (SetThreadContext (th->h, &th->context));
-	      th->context.ContextFlags = 0;
-	    }
-	}
 
   debug_registers_changed = 0;
   return res;
@@ -1233,8 +1244,7 @@ win32_resume (ptid_t ptid, int step, enu
 	      th->context.Dr1 = dr[1];
 	      th->context.Dr2 = dr[2];
 	      th->context.Dr3 = dr[3];
-	      /* th->context.Dr6 = dr[6];
-	       FIXME: should we set dr6 also ?? */
+	      th->context.Dr6 = 0xffff0ff0;
 	      th->context.Dr7 = dr[7];
 	    }
 	  CHECK (SetThreadContext (th->h, &th->context));



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

* RE: [win32] Fix suspend count handling
  2007-11-21 23:33           ` Pedro Alves
@ 2007-11-22  9:19             ` Pierre Muller
  2007-11-23  1:07             ` Christopher Faylor
  1 sibling, 0 replies; 28+ messages in thread
From: Pierre Muller @ 2007-11-22  9:19 UTC (permalink / raw)
  To: 'Pedro Alves'; +Cc: gdb-patches

  I checked again the new patch and
the testsuite results are exactly the
same as I already reported for the hardware watchpoint fix
alone.
  I think that this patch is good,
but only Christopher can approve it.

Pierre

> -----Original Message-----
> From: gdb-patches-owner@sourceware.org [mailto:gdb-patches-
> owner@sourceware.org] On Behalf Of Pedro Alves
> Sent: Thursday, November 22, 2007 12:19 AM
> To: Pierre Muller
> Cc: gdb-patches@sourceware.org
> Subject: Re: [win32] Fix suspend count handling
> 
> Pedro Alves wrote:
> > Pedro Alves wrote:
> >> On Nov 21, 2007 2:13 PM, Pierre Muller wrote:
> >> That's not what I see here.  Can you show me a run where you get 4
> >> only this patch applied?
> >>
> >
> > I did try that, but posted a log of not doing it :-).
> >
> > I've just tried about 30 times, and only once I did see a 4 coming
> out
> > ...  oh, well, one of those things.
> >
> 
> OK.  Back at my home laptop, I can reproduce that with no problems.
> Let me clarify what the 4 problem really is.
> It's a race between gdb and the inferior.
> 
> Take this slightly changed test case.  The only difference to the
> original version is the extra Sleep call.
> 
> #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;
>          }
> 
>      Sleep (300);
> 
>      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;
> }
> 
> If you do the "break at ...", "run", "thread 3", "continue"
> sequence, and "..." is the "Sleep" line, you'll get 3, but if you put
> the break at the /* set breakpoint here */ line, you'll get 4 (if
> you're (un)lucky).
> 
> The race happens due to the fact that gdb is doing something similar to
> this:
> 
> win32_continue()
> {
>     ContinueDebugEvent (...);  /* Resumes all non suspended
>                                   threads of the process.  */
> 
>     /* At this point, gdb is running concurrently with
>        the inferior threads that were not suspended - which
>        included the main thread of the testcase.  */
>     foreach t in threads do
>        if t is suspended
>           ResumeThread t
>        fi
>     done
> }
> 
> If you break at the Sleep call, when we resume, gdb will have a bit of
> time to call ResumeThread on the suspended thread of the testcase.  If
> you instead break at the ResumeThread line, you'll have a good chance
> that the inferior wins the race, hence the "4" result (remember that
> ResumeThread returns the previous suspend count).
> If we put something like this after the ResumeThread call:
> 
>      (...)
>      suspend_count = ResumeThread (h); /* set breakpoint here */
> 
> +  Sleep (300);
> +  SuspendThread (h);
> +  suspend_count = ResumeThread (h);
> 
>      printf ("%lu\n", suspend_count); /* should be 3 */
>      (...)
> 
> ... you'll see that eventually gdb will bring the suspend count back to
> 3.  (A SuspendThread, ResumeThread pair is the way to get at the
> suspend count.)
> 
> > Since the watchpoint patch should fix this, what shall I do?  Shall I
> > merge the two and resubmit, or leave it at that ?  They've already
> > been tested together without regressions.
> >
> 
> Here is the merge from the patch I posted at the start of the thread
> with this patch:
>     [win32] Fix watchpoint support
>     http://sourceware.org/ml/gdb-patches/2007-11/msg00390.html
> 
> This patch fixes both the suspend_count
> handling, and the watchpoint support.
> 
> Thanks Pierre, for looking at it.
> 
> OK ?
> 
> --
> Pedro Alves



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

* Re: [win32] Fix suspend count handling
  2007-11-21 23:33           ` Pedro Alves
  2007-11-22  9:19             ` Pierre Muller
@ 2007-11-23  1:07             ` Christopher Faylor
  2007-11-23 10:19               ` Lerele
  2007-11-24 12:16               ` Pedro Alves
  1 sibling, 2 replies; 28+ messages in thread
From: Christopher Faylor @ 2007-11-23  1:07 UTC (permalink / raw)
  To: gdb-patches

On Wed, Nov 21, 2007 at 11:18:38PM +0000, Pedro Alves wrote:
> Pedro Alves wrote:
>> Pedro Alves wrote:
>>> On Nov 21, 2007 2:13 PM, Pierre Muller wrote:
>>> That's not what I see here.  Can you show me a run where you get 4
>>> only this patch applied?
>>>
>> I did try that, but posted a log of not doing it :-).
>> I've just tried about 30 times, and only once I did see
>> a 4 coming out ...  oh, well, one of those things.
>
> OK.  Back at my home laptop, I can reproduce that with
> no problems.  Let me clarify what the 4 problem really is.
> It's a race between gdb and the inferior.
>
> Take this slightly changed test case.  The only difference
> to the original version is the extra Sleep call.
>
> #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;
>         }
>
>     Sleep (300);
>
>     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;
> }
>
> If you do the "break at ...", "run", "thread 3", "continue"
> sequence, and "..." is the "Sleep" line, you'll get 3,
> but if you put the break at the /* set breakpoint here */
> line, you'll get 4 (if you're (un)lucky).
>
> The race happens due to the fact that gdb is
> doing something similar to this:
>
> win32_continue()
> {
>    ContinueDebugEvent (...);  /* Resumes all non suspended
>                                  threads of the process.  */
>
>    /* At this point, gdb is running concurrently with
>       the inferior threads that were not suspended - which
>       included the main thread of the testcase.  */
>    foreach t in threads do
>       if t is suspended
>          ResumeThread t
>       fi
>    done
> }
>
> If you break at the Sleep call, when we resume, gdb will
> have a bit of time to call ResumeThread on the suspended
> thread of the testcase.  If you instead break at the
> ResumeThread line, you'll have a good chance that the
> inferior wins the race, hence the "4" result (remember
> that ResumeThread returns the previous suspend count).
> If we put something like this after the ResumeThread call:
>
>     (...)
>     suspend_count = ResumeThread (h); /* set breakpoint here */
>
> +  Sleep (300);
> +  SuspendThread (h);
> +  suspend_count = ResumeThread (h);
>
>     printf ("%lu\n", suspend_count); /* should be 3 */
>     (...)
>
> ... you'll see that eventually gdb will bring the
> suspend count back to 3.  (A SuspendThread, ResumeThread
> pair is the way to get at the suspend count.)
>
>> Since the watchpoint patch should fix this, what shall I do?  Shall I 
>> merge
>> the two and resubmit, or leave it at that ?  They've already been tested
>> together without regressions.
>
> Here is the merge from the patch I posted at the start of the
> thread with this patch:
>    [win32] Fix watchpoint support
>    http://sourceware.org/ml/gdb-patches/2007-11/msg00390.html
>
> This patch fixes both the suspend_count
> handling, and the watchpoint support.
>
> Thanks Pierre, for looking at it.
>
> OK ?
>
> -- 
> Pedro Alves

>2007-11-21  Pedro Alves  <pedro_alves@portugalmail.pt>
>
>	* win32-nat.c (thread_info_struct): Rename suspend_count to
>	suspended, to be used as a flag.
>	(thread_rec): Only suspend the thread if it wasn't suspended by
>	gdb before.  Warn if suspending failed.
>	(win32_add_thread): Set Dr6 to 0xffff0ff0.
>	(win32_resume): Likewise.
>	(win32_continue): Set Dr6 to 0xffff0ff0.  Update usage of the
>	`suspended' flag.  Do ContinueDebugEvent after resuming the
>	suspended threads, not before.  Set threads' contexts before
>	resuming them, not after.


>---
> gdb/win32-nat.c |   80 +++++++++++++++++++++++++++++++-------------------------
> 1 file changed, 45 insertions(+), 35 deletions(-)
>
>Index: src/gdb/win32-nat.c
>===================================================================
>--- src.orig/gdb/win32-nat.c	2007-11-11 23:13:04.000000000 +0000
>+++ src/gdb/win32-nat.c	2007-11-21 22:39:56.000000000 +0000
>@@ -112,14 +112,14 @@ static enum target_signal last_sig = TAR
> /* Set if a signal was received from the debugged process */
> 
> /* Thread information structure used to track information that is
>-   not available in gdb's thread structure. */
>+   not available in gdb's thread structure.  */
> typedef struct thread_info_struct
>   {
>     struct thread_info_struct *next;
>     DWORD id;
>     HANDLE h;
>     char *name;
>-    int suspend_count;
>+    int suspended;
>     int reload_context;
>     CONTEXT context;
>     STACKFRAME sf;
>@@ -244,9 +244,10 @@ check (BOOL ok, const char *file, int li
> 		     GetLastError ());
> }
> 
>-/* Find a thread record given a thread id.
>-   If get_context then also retrieve the context for this
>-   thread. */
>+/* Find a thread record given a thread id passed in ID.  If
>+   GET_CONTEXT is not 0, then also retrieve the context for this
>+   thread.  If GET_CONTEXT is negative, then don't suspend the
>+   thread.  */

I don't see any reason to capitalize get_context in the comment.

> static thread_info *
> thread_rec (DWORD id, int get_context)
> {
>@@ -255,12 +256,21 @@ thread_rec (DWORD id, int get_context)
>   for (th = &thread_head; (th = th->next) != NULL;)
>     if (th->id == id)
>       {
>-	if (!th->suspend_count && get_context)
>+	if (!th->suspended && get_context)
> 	  {
> 	    if (get_context > 0 && id != current_event.dwThreadId)
>-	      th->suspend_count = SuspendThread (th->h) + 1;
>+	      {
>+		if (SuspendThread (th->h) == (DWORD) -1)
>+		  {
>+		    DWORD err = GetLastError ();
>+		    warning (_("SuspendThread failed. (winerr %d)"),
>+			     (int) err);
>+		    return NULL;
>+		  }
>+		th->suspended = 1;
>+	      }
> 	    else if (get_context < 0)
>-	      th->suspend_count = -1;
>+	      th->suspended = -1;
> 	    th->reload_context = 1;
> 	  }
> 	return th;
>@@ -294,8 +304,7 @@ win32_add_thread (DWORD id, HANDLE h)
>       th->context.Dr1 = dr[1];
>       th->context.Dr2 = dr[2];
>       th->context.Dr3 = dr[3];
>-      /* th->context.Dr6 = dr[6];
>-      FIXME: should we set dr6 also ?? */
>+      th->context.Dr6 = 0xffff0ff0;

This, and similar cases, needs to use a #define with an explanatory comment.

With the above minor changes, this looks ok.

I have to ask, however, if the SuspendThread's are even needed at all.
When I was writing this code, I wasn't entirely sure that gdb needed to
do anything like this but I erred on the side of caution.  So, I'm
wondering if things would still work ok if the
SuspendThread/ResumeThread stuff was gone.

cgf


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

* Re: [win32] Fix suspend count handling
  2007-11-23  1:07             ` Christopher Faylor
@ 2007-11-23 10:19               ` Lerele
  2007-11-23 18:30                 ` Lerele
  2007-11-24  5:33                 ` Christopher Faylor
  2007-11-24 12:16               ` Pedro Alves
  1 sibling, 2 replies; 28+ messages in thread
From: Lerele @ 2007-11-23 10:19 UTC (permalink / raw)
  To: gdb-patches

Christopher Faylor escribió:
> On Wed, Nov 21, 2007 at 11:18:38PM +0000, Pedro Alves wrote:
>   
>> Pedro Alves wrote:
>>     
>>> Pedro Alves wrote:
>>>       
>>>> On Nov 21, 2007 2:13 PM, Pierre Muller wrote:
>>>> That's not what I see here.  Can you show me a run where you get 4
>>>> only this patch applied?
>>>>
>>>>         
>>> I did try that, but posted a log of not doing it :-).
>>> I've just tried about 30 times, and only once I did see
>>> a 4 coming out ...  oh, well, one of those things.
>>>       
>> OK.  Back at my home laptop, I can reproduce that with
>> no problems.  Let me clarify what the 4 problem really is.
>> It's a race between gdb and the inferior.
>>
>> Take this slightly changed test case.  The only difference
>> to the original version is the extra Sleep call.
>>
>> #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;
>>         }
>>
>>     Sleep (300);
>>
>>     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;
>> }
>>
>> If you do the "break at ...", "run", "thread 3", "continue"
>> sequence, and "..." is the "Sleep" line, you'll get 3,
>> but if you put the break at the /* set breakpoint here */
>> line, you'll get 4 (if you're (un)lucky).
>>
>> The race happens due to the fact that gdb is
>> doing something similar to this:
>>
>> win32_continue()
>> {
>>    ContinueDebugEvent (...);  /* Resumes all non suspended
>>                                  threads of the process.  */
>>
>>    /* At this point, gdb is running concurrently with
>>       the inferior threads that were not suspended - which
>>       included the main thread of the testcase.  */
>>    foreach t in threads do
>>       if t is suspended
>>          ResumeThread t
>>       fi
>>    done
>> }
>>
>> If you break at the Sleep call, when we resume, gdb will
>> have a bit of time to call ResumeThread on the suspended
>> thread of the testcase.  If you instead break at the
>> ResumeThread line, you'll have a good chance that the
>> inferior wins the race, hence the "4" result (remember
>> that ResumeThread returns the previous suspend count).
>> If we put something like this after the ResumeThread call:
>>
>>     (...)
>>     suspend_count = ResumeThread (h); /* set breakpoint here */
>>
>> +  Sleep (300);
>> +  SuspendThread (h);
>> +  suspend_count = ResumeThread (h);
>>
>>     printf ("%lu\n", suspend_count); /* should be 3 */
>>     (...)
>>
>> ... you'll see that eventually gdb will bring the
>> suspend count back to 3.  (A SuspendThread, ResumeThread
>> pair is the way to get at the suspend count.)
>>
>>     
>>> Since the watchpoint patch should fix this, what shall I do?  Shall I 
>>> merge
>>> the two and resubmit, or leave it at that ?  They've already been tested
>>> together without regressions.
>>>       
>> Here is the merge from the patch I posted at the start of the
>> thread with this patch:
>>    [win32] Fix watchpoint support
>>    http://sourceware.org/ml/gdb-patches/2007-11/msg00390.html
>>
>> This patch fixes both the suspend_count
>> handling, and the watchpoint support.
>>
>> Thanks Pierre, for looking at it.
>>
>> OK ?
>>
>> -- 
>> Pedro Alves
>>     
>
>   
>> 2007-11-21  Pedro Alves  <pedro_alves@portugalmail.pt>
>>
>> 	* win32-nat.c (thread_info_struct): Rename suspend_count to
>> 	suspended, to be used as a flag.
>> 	(thread_rec): Only suspend the thread if it wasn't suspended by
>> 	gdb before.  Warn if suspending failed.
>> 	(win32_add_thread): Set Dr6 to 0xffff0ff0.
>> 	(win32_resume): Likewise.
>> 	(win32_continue): Set Dr6 to 0xffff0ff0.  Update usage of the
>> 	`suspended' flag.  Do ContinueDebugEvent after resuming the
>> 	suspended threads, not before.  Set threads' contexts before
>> 	resuming them, not after.
>>     
>
>
>   
>> ---
>> gdb/win32-nat.c |   80 +++++++++++++++++++++++++++++++-------------------------
>> 1 file changed, 45 insertions(+), 35 deletions(-)
>>
>> Index: src/gdb/win32-nat.c
>> ===================================================================
>> --- src.orig/gdb/win32-nat.c	2007-11-11 23:13:04.000000000 +0000
>> +++ src/gdb/win32-nat.c	2007-11-21 22:39:56.000000000 +0000
>> @@ -112,14 +112,14 @@ static enum target_signal last_sig = TAR
>> /* Set if a signal was received from the debugged process */
>>
>> /* Thread information structure used to track information that is
>> -   not available in gdb's thread structure. */
>> +   not available in gdb's thread structure.  */
>> typedef struct thread_info_struct
>>   {
>>     struct thread_info_struct *next;
>>     DWORD id;
>>     HANDLE h;
>>     char *name;
>> -    int suspend_count;
>> +    int suspended;
>>     int reload_context;
>>     CONTEXT context;
>>     STACKFRAME sf;
>> @@ -244,9 +244,10 @@ check (BOOL ok, const char *file, int li
>> 		     GetLastError ());
>> }
>>
>> -/* Find a thread record given a thread id.
>> -   If get_context then also retrieve the context for this
>> -   thread. */
>> +/* Find a thread record given a thread id passed in ID.  If
>> +   GET_CONTEXT is not 0, then also retrieve the context for this
>> +   thread.  If GET_CONTEXT is negative, then don't suspend the
>> +   thread.  */
>>     
>
> I don't see any reason to capitalize get_context in the comment.
>
>   
>> static thread_info *
>> thread_rec (DWORD id, int get_context)
>> {
>> @@ -255,12 +256,21 @@ thread_rec (DWORD id, int get_context)
>>   for (th = &thread_head; (th = th->next) != NULL;)
>>     if (th->id == id)
>>       {
>> -	if (!th->suspend_count && get_context)
>> +	if (!th->suspended && get_context)
>> 	  {
>> 	    if (get_context > 0 && id != current_event.dwThreadId)
>> -	      th->suspend_count = SuspendThread (th->h) + 1;
>> +	      {
>> +		if (SuspendThread (th->h) == (DWORD) -1)
>> +		  {
>> +		    DWORD err = GetLastError ();
>> +		    warning (_("SuspendThread failed. (winerr %d)"),
>> +			     (int) err);
>> +		    return NULL;
>> +		  }
>> +		th->suspended = 1;
>> +	      }
>> 	    else if (get_context < 0)
>> -	      th->suspend_count = -1;
>> +	      th->suspended = -1;
>> 	    th->reload_context = 1;
>> 	  }
>> 	return th;
>> @@ -294,8 +304,7 @@ win32_add_thread (DWORD id, HANDLE h)
>>       th->context.Dr1 = dr[1];
>>       th->context.Dr2 = dr[2];
>>       th->context.Dr3 = dr[3];
>> -      /* th->context.Dr6 = dr[6];
>> -      FIXME: should we set dr6 also ?? */
>> +      th->context.Dr6 = 0xffff0ff0;
>>     
>
> This, and similar cases, needs to use a #define with an explanatory comment.
>
> With the above minor changes, this looks ok.
>
> I have to ask, however, if the SuspendThread's are even needed at all.
> When I was writing this code, I wasn't entirely sure that gdb needed to
> do anything like this but I erred on the side of caution.  So, I'm
> wondering if things would still work ok if the
> SuspendThread/ResumeThread stuff was gone.
>
> cgf
>
>   

I think they are needed. They were anyway with the new gdbserver based 
(vs. Win32 API based) interrupt code I sent several days ago, and that 
so very kindly Pedro prepared for commitment, but that I still haven't 
found the time to sit down and look at them (however I'm absolutely sure 
they're just fine), I guess his changes must be similar to what I sent 
in the first place.
Apart from this, there's also the case where (at least for gdbserver) 
socket data is received asynchronously while the child is running. This 
socket data could indicate gdbserver to set/enable/disable a breakpoint, 
read thread registers, etc., and this kind of things may require to stop 
the child using SuspendThread.
Right?

Leo.



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

* Re: [win32] Fix suspend count handling
  2007-11-23 10:19               ` Lerele
@ 2007-11-23 18:30                 ` Lerele
  2007-11-24 12:43                   ` Pedro Alves
  2007-11-24  5:33                 ` Christopher Faylor
  1 sibling, 1 reply; 28+ messages in thread
From: Lerele @ 2007-11-23 18:30 UTC (permalink / raw)
  To: gdb-patches

Lerele escribió:
> Christopher Faylor escribió:
>> On Wed, Nov 21, 2007 at 11:18:38PM +0000, Pedro Alves wrote:
>>  
>>> Pedro Alves wrote:
>>>    
>>>> Pedro Alves wrote:
>>>>      
>>>>> On Nov 21, 2007 2:13 PM, Pierre Muller wrote:
>>>>> That's not what I see here.  Can you show me a run where you get 4
>>>>> only this patch applied?
>>>>>
>>>>>         
>>>> I did try that, but posted a log of not doing it :-).
>>>> I've just tried about 30 times, and only once I did see
>>>> a 4 coming out ...  oh, well, one of those things.
>>>>       
>>> OK.  Back at my home laptop, I can reproduce that with
>>> no problems.  Let me clarify what the 4 problem really is.
>>> It's a race between gdb and the inferior.
>>>
>>> Take this slightly changed test case.  The only difference
>>> to the original version is the extra Sleep call.
>>>
>>> #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;
>>>         }
>>>
>>>     Sleep (300);
>>>
>>>     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;
>>> }
>>>
>>> If you do the "break at ...", "run", "thread 3", "continue"
>>> sequence, and "..." is the "Sleep" line, you'll get 3,
>>> but if you put the break at the /* set breakpoint here */
>>> line, you'll get 4 (if you're (un)lucky).
>>>
>>> The race happens due to the fact that gdb is
>>> doing something similar to this:
>>>
>>> win32_continue()
>>> {
>>>    ContinueDebugEvent (...);  /* Resumes all non suspended
>>>                                  threads of the process.  */
>>>
>>>    /* At this point, gdb is running concurrently with
>>>       the inferior threads that were not suspended - which
>>>       included the main thread of the testcase.  */
>>>    foreach t in threads do
>>>       if t is suspended
>>>          ResumeThread t
>>>       fi
>>>    done
>>> }
>>>
>>> If you break at the Sleep call, when we resume, gdb will
>>> have a bit of time to call ResumeThread on the suspended
>>> thread of the testcase.  If you instead break at the
>>> ResumeThread line, you'll have a good chance that the
>>> inferior wins the race, hence the "4" result (remember
>>> that ResumeThread returns the previous suspend count).
>>> If we put something like this after the ResumeThread call:
>>>
>>>     (...)
>>>     suspend_count = ResumeThread (h); /* set breakpoint here */
>>>
>>> +  Sleep (300);
>>> +  SuspendThread (h);
>>> +  suspend_count = ResumeThread (h);
>>>
>>>     printf ("%lu\n", suspend_count); /* should be 3 */
>>>     (...)
>>>
>>> ... you'll see that eventually gdb will bring the
>>> suspend count back to 3.  (A SuspendThread, ResumeThread
>>> pair is the way to get at the suspend count.)
>>>
>>>    
>>>> Since the watchpoint patch should fix this, what shall I do?  Shall 
>>>> I merge
>>>> the two and resubmit, or leave it at that ?  They've already been 
>>>> tested
>>>> together without regressions.
>>>>       
>>> Here is the merge from the patch I posted at the start of the
>>> thread with this patch:
>>>    [win32] Fix watchpoint support
>>>    http://sourceware.org/ml/gdb-patches/2007-11/msg00390.html
>>>
>>> This patch fixes both the suspend_count
>>> handling, and the watchpoint support.
>>>
>>> Thanks Pierre, for looking at it.
>>>
>>> OK ?
>>>
>>> -- 
>>> Pedro Alves
>>>     
>>
>>  
>>> 2007-11-21  Pedro Alves  <pedro_alves@portugalmail.pt>
>>>
>>>     * win32-nat.c (thread_info_struct): Rename suspend_count to
>>>     suspended, to be used as a flag.
>>>     (thread_rec): Only suspend the thread if it wasn't suspended by
>>>     gdb before.  Warn if suspending failed.
>>>     (win32_add_thread): Set Dr6 to 0xffff0ff0.
>>>     (win32_resume): Likewise.
>>>     (win32_continue): Set Dr6 to 0xffff0ff0.  Update usage of the
>>>     `suspended' flag.  Do ContinueDebugEvent after resuming the
>>>     suspended threads, not before.  Set threads' contexts before
>>>     resuming them, not after.
>>>     
>>
>>
>>  
>>> ---
>>> gdb/win32-nat.c |   80 
>>> +++++++++++++++++++++++++++++++-------------------------
>>> 1 file changed, 45 insertions(+), 35 deletions(-)
>>>
>>> Index: src/gdb/win32-nat.c
>>> ===================================================================
>>> --- src.orig/gdb/win32-nat.c    2007-11-11 23:13:04.000000000 +0000
>>> +++ src/gdb/win32-nat.c    2007-11-21 22:39:56.000000000 +0000
>>> @@ -112,14 +112,14 @@ static enum target_signal last_sig = TAR
>>> /* Set if a signal was received from the debugged process */
>>>
>>> /* Thread information structure used to track information that is
>>> -   not available in gdb's thread structure. */
>>> +   not available in gdb's thread structure.  */
>>> typedef struct thread_info_struct
>>>   {
>>>     struct thread_info_struct *next;
>>>     DWORD id;
>>>     HANDLE h;
>>>     char *name;
>>> -    int suspend_count;
>>> +    int suspended;
>>>     int reload_context;
>>>     CONTEXT context;
>>>     STACKFRAME sf;
>>> @@ -244,9 +244,10 @@ check (BOOL ok, const char *file, int li
>>>              GetLastError ());
>>> }
>>>
>>> -/* Find a thread record given a thread id.
>>> -   If get_context then also retrieve the context for this
>>> -   thread. */
>>> +/* Find a thread record given a thread id passed in ID.  If
>>> +   GET_CONTEXT is not 0, then also retrieve the context for this
>>> +   thread.  If GET_CONTEXT is negative, then don't suspend the
>>> +   thread.  */
>>>     
>>
>> I don't see any reason to capitalize get_context in the comment.
>>
>>  
>>> static thread_info *
>>> thread_rec (DWORD id, int get_context)
>>> {
>>> @@ -255,12 +256,21 @@ thread_rec (DWORD id, int get_context)
>>>   for (th = &thread_head; (th = th->next) != NULL;)
>>>     if (th->id == id)
>>>       {
>>> -    if (!th->suspend_count && get_context)
>>> +    if (!th->suspended && get_context)
>>>       {
>>>         if (get_context > 0 && id != current_event.dwThreadId)
>>> -          th->suspend_count = SuspendThread (th->h) + 1;
>>> +          {
>>> +        if (SuspendThread (th->h) == (DWORD) -1)
>>> +          {
>>> +            DWORD err = GetLastError ();
>>> +            warning (_("SuspendThread failed. (winerr %d)"),
>>> +                 (int) err);
>>> +            return NULL;
>>> +          }
>>> +        th->suspended = 1;
>>> +          }
>>>         else if (get_context < 0)
>>> -          th->suspend_count = -1;
>>> +          th->suspended = -1;
>>>         th->reload_context = 1;
>>>       }
>>>     return th;
>>> @@ -294,8 +304,7 @@ win32_add_thread (DWORD id, HANDLE h)
>>>       th->context.Dr1 = dr[1];
>>>       th->context.Dr2 = dr[2];
>>>       th->context.Dr3 = dr[3];
>>> -      /* th->context.Dr6 = dr[6];
>>> -      FIXME: should we set dr6 also ?? */
>>> +      th->context.Dr6 = 0xffff0ff0;
>>>     
>>
>> This, and similar cases, needs to use a #define with an explanatory 
>> comment.
>>
>> With the above minor changes, this looks ok.
>>
>> I have to ask, however, if the SuspendThread's are even needed at all.
>> When I was writing this code, I wasn't entirely sure that gdb needed to
>> do anything like this but I erred on the side of caution.  So, I'm
>> wondering if things would still work ok if the
>> SuspendThread/ResumeThread stuff was gone.
>>
>> cgf
>>
>>   
>
> I think they are needed. They were anyway with the new gdbserver based 
> (vs. Win32 API based) interrupt code I sent several days ago, and that 
> so very kindly Pedro prepared for commitment, but that I still haven't 
> found the time to sit down and look at them (however I'm absolutely 
> sure they're just fine), I guess his changes must be similar to what I 
> sent in the first place.
> Apart from this, there's also the case where (at least for gdbserver) 
> socket data is received asynchronously while the child is running. 
> This socket data could indicate gdbserver to set/enable/disable a 
> breakpoint, read thread registers, etc., and this kind of things may 
> require to stop the child using SuspendThread.
> Right?
>
> Leo.
>
>


I'd also like to ask you a question, concerning a comment from Pedro 
several messages back that has stayed around in my mind since then.

It's not related with this specific thread title, but since it's 
gdbserver/win32 related, I haven't found appropriate to open a new 
thread just for this simple question.

The issue is near the end of:
http://sourceware.org/ml/gdb-patches/2007-11/msg00041.html

It's about the fact of gdb win32-nat.c some time ago having the 
interrupt functionality similar to the one that has been recently 
implemented using SuspendThread (versus using DebugBreak kind of 
functions). Pedro commented back then that win32-nat.c did have sometime 
in the past a similar implementation [that must have been dropped].
Do you know/remember if it was dropped for a specific reason?

My concern is about any possible drawback for this new interrupt 
functionality method.

Regards,
Leo.




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

* Re: [win32] Fix suspend count handling
  2007-11-23 10:19               ` Lerele
  2007-11-23 18:30                 ` Lerele
@ 2007-11-24  5:33                 ` Christopher Faylor
  2007-11-24 14:18                   ` Lerele
  1 sibling, 1 reply; 28+ messages in thread
From: Christopher Faylor @ 2007-11-24  5:33 UTC (permalink / raw)
  To: gdb-patches

On Fri, Nov 23, 2007 at 11:19:14AM +0100, Lerele wrote:
> Christopher Faylor escribi?:
>> On Wed, Nov 21, 2007 at 11:18:38PM +0000, Pedro Alves wrote:
>>   
>>> Pedro Alves wrote:
>>>     
>>>> Pedro Alves wrote:
>>>>       
>>>>> On Nov 21, 2007 2:13 PM, Pierre Muller wrote:
>>>>> That's not what I see here.  Can you show me a run where you get 4
>>>>> only this patch applied?
>>>>>
>>>>>         
>>>> I did try that, but posted a log of not doing it :-).
>>>> I've just tried about 30 times, and only once I did see
>>>> a 4 coming out ...  oh, well, one of those things.
>>>>       
>>> OK.  Back at my home laptop, I can reproduce that with
>>> no problems.  Let me clarify what the 4 problem really is.
>>> It's a race between gdb and the inferior.
>>>
>>> Take this slightly changed test case.  The only difference
>>> to the original version is the extra Sleep call.
>>>
>>> #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;
>>>         }
>>>
>>>     Sleep (300);
>>>
>>>     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;
>>> }
>>>
>>> If you do the "break at ...", "run", "thread 3", "continue"
>>> sequence, and "..." is the "Sleep" line, you'll get 3,
>>> but if you put the break at the /* set breakpoint here */
>>> line, you'll get 4 (if you're (un)lucky).
>>>
>>> The race happens due to the fact that gdb is
>>> doing something similar to this:
>>>
>>> win32_continue()
>>> {
>>>    ContinueDebugEvent (...);  /* Resumes all non suspended
>>>                                  threads of the process.  */
>>>
>>>    /* At this point, gdb is running concurrently with
>>>       the inferior threads that were not suspended - which
>>>       included the main thread of the testcase.  */
>>>    foreach t in threads do
>>>       if t is suspended
>>>          ResumeThread t
>>>       fi
>>>    done
>>> }
>>>
>>> If you break at the Sleep call, when we resume, gdb will
>>> have a bit of time to call ResumeThread on the suspended
>>> thread of the testcase.  If you instead break at the
>>> ResumeThread line, you'll have a good chance that the
>>> inferior wins the race, hence the "4" result (remember
>>> that ResumeThread returns the previous suspend count).
>>> If we put something like this after the ResumeThread call:
>>>
>>>     (...)
>>>     suspend_count = ResumeThread (h); /* set breakpoint here */
>>>
>>> +  Sleep (300);
>>> +  SuspendThread (h);
>>> +  suspend_count = ResumeThread (h);
>>>
>>>     printf ("%lu\n", suspend_count); /* should be 3 */
>>>     (...)
>>>
>>> ... you'll see that eventually gdb will bring the
>>> suspend count back to 3.  (A SuspendThread, ResumeThread
>>> pair is the way to get at the suspend count.)
>>>
>>>     
>>>> Since the watchpoint patch should fix this, what shall I do?  Shall I 
>>>> merge
>>>> the two and resubmit, or leave it at that ?  They've already been tested
>>>> together without regressions.
>>>>       
>>> Here is the merge from the patch I posted at the start of the
>>> thread with this patch:
>>>    [win32] Fix watchpoint support
>>>    http://sourceware.org/ml/gdb-patches/2007-11/msg00390.html
>>>
>>> This patch fixes both the suspend_count
>>> handling, and the watchpoint support.
>>>
>>> Thanks Pierre, for looking at it.
>>>
>>> OK ?
>>>
>>> -- 
>>> Pedro Alves
>>>     
>>
>>   
>>> 2007-11-21  Pedro Alves  <pedro_alves@portugalmail.pt>
>>>
>>> 	* win32-nat.c (thread_info_struct): Rename suspend_count to
>>> 	suspended, to be used as a flag.
>>> 	(thread_rec): Only suspend the thread if it wasn't suspended by
>>> 	gdb before.  Warn if suspending failed.
>>> 	(win32_add_thread): Set Dr6 to 0xffff0ff0.
>>> 	(win32_resume): Likewise.
>>> 	(win32_continue): Set Dr6 to 0xffff0ff0.  Update usage of the
>>> 	`suspended' flag.  Do ContinueDebugEvent after resuming the
>>> 	suspended threads, not before.  Set threads' contexts before
>>> 	resuming them, not after.
>>>     
>>
>>
>>   
>>> ---
>>> gdb/win32-nat.c |   80 
>>> +++++++++++++++++++++++++++++++-------------------------
>>> 1 file changed, 45 insertions(+), 35 deletions(-)
>>>
>>> Index: src/gdb/win32-nat.c
>>> ===================================================================
>>> --- src.orig/gdb/win32-nat.c	2007-11-11 23:13:04.000000000 +0000
>>> +++ src/gdb/win32-nat.c	2007-11-21 22:39:56.000000000 +0000
>>> @@ -112,14 +112,14 @@ static enum target_signal last_sig = TAR
>>> /* Set if a signal was received from the debugged process */
>>>
>>> /* Thread information structure used to track information that is
>>> -   not available in gdb's thread structure. */
>>> +   not available in gdb's thread structure.  */
>>> typedef struct thread_info_struct
>>>   {
>>>     struct thread_info_struct *next;
>>>     DWORD id;
>>>     HANDLE h;
>>>     char *name;
>>> -    int suspend_count;
>>> +    int suspended;
>>>     int reload_context;
>>>     CONTEXT context;
>>>     STACKFRAME sf;
>>> @@ -244,9 +244,10 @@ check (BOOL ok, const char *file, int li
>>> 		     GetLastError ());
>>> }
>>>
>>> -/* Find a thread record given a thread id.
>>> -   If get_context then also retrieve the context for this
>>> -   thread. */
>>> +/* Find a thread record given a thread id passed in ID.  If
>>> +   GET_CONTEXT is not 0, then also retrieve the context for this
>>> +   thread.  If GET_CONTEXT is negative, then don't suspend the
>>> +   thread.  */
>>>     
>>
>> I don't see any reason to capitalize get_context in the comment.
>>
>>   
>>> static thread_info *
>>> thread_rec (DWORD id, int get_context)
>>> {
>>> @@ -255,12 +256,21 @@ thread_rec (DWORD id, int get_context)
>>>   for (th = &thread_head; (th = th->next) != NULL;)
>>>     if (th->id == id)
>>>       {
>>> -	if (!th->suspend_count && get_context)
>>> +	if (!th->suspended && get_context)
>>> 	  {
>>> 	    if (get_context > 0 && id != current_event.dwThreadId)
>>> -	      th->suspend_count = SuspendThread (th->h) + 1;
>>> +	      {
>>> +		if (SuspendThread (th->h) == (DWORD) -1)
>>> +		  {
>>> +		    DWORD err = GetLastError ();
>>> +		    warning (_("SuspendThread failed. (winerr %d)"),
>>> +			     (int) err);
>>> +		    return NULL;
>>> +		  }
>>> +		th->suspended = 1;
>>> +	      }
>>> 	    else if (get_context < 0)
>>> -	      th->suspend_count = -1;
>>> +	      th->suspended = -1;
>>> 	    th->reload_context = 1;
>>> 	  }
>>> 	return th;
>>> @@ -294,8 +304,7 @@ win32_add_thread (DWORD id, HANDLE h)
>>>       th->context.Dr1 = dr[1];
>>>       th->context.Dr2 = dr[2];
>>>       th->context.Dr3 = dr[3];
>>> -      /* th->context.Dr6 = dr[6];
>>> -      FIXME: should we set dr6 also ?? */
>>> +      th->context.Dr6 = 0xffff0ff0;
>>>     
>>
>> This, and similar cases, needs to use a #define with an explanatory 
>> comment.
>>
>> With the above minor changes, this looks ok.
>>
>> I have to ask, however, if the SuspendThread's are even needed at all.
>> When I was writing this code, I wasn't entirely sure that gdb needed to
>> do anything like this but I erred on the side of caution.  So, I'm
>> wondering if things would still work ok if the
>> SuspendThread/ResumeThread stuff was gone.
>
>I think they are needed.  They were anyway with the new gdbserver based
>(vs.  Win32 API based) interrupt code I sent several days ago, and that
>so very kindly Pedro prepared for commitment, but that I still haven't
>found the time to sit down and look at them (however I'm absolutely
>sure they're just fine), I guess his changes must be similar to what I
>sent in the first place.

*Why* did you think you needed them in gdbserver?  Did you actually try
not using them or did you just copy my code from win32-nat.c?

> Apart from this, there's also the case where (at least for gdbserver) 
> socket data is received asynchronously while the child is running. This 
> socket data could indicate gdbserver to set/enable/disable a breakpoint, 
> read thread registers, etc., and this kind of things may require to stop 
> the child using SuspendThread.
> Right?

I don't know exactly what you are referring to but if you are proposing
using SuspendThread/ResumeThread to work around non UNIX-like handling
of signals, I've previously mentioned that the use of SuspendThread is
dangerous since, the last I checked, Windows wasn't very good about not
avoiding reentracy problems if you suspend a thread and then use another
funcion from the Windows API.  This used to cause strange random
behavior and even blue screens in older versions of Windows NT.  I guess
it's possible that it's better these days but there is no way to really
know for sure.

cgf


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

* Re: [win32] Fix suspend count handling
  2007-11-23  1:07             ` Christopher Faylor
  2007-11-23 10:19               ` Lerele
@ 2007-11-24 12:16               ` Pedro Alves
  2007-11-24 20:51                 ` Christopher Faylor
  1 sibling, 1 reply; 28+ messages in thread
From: Pedro Alves @ 2007-11-24 12:16 UTC (permalink / raw)
  To: gdb-patches

[-- Attachment #1: Type: text/plain, Size: 2487 bytes --]

Christopher Faylor wrote:

>> -/* Find a thread record given a thread id.
>> -   If get_context then also retrieve the context for this
>> -   thread. */
>> +/* Find a thread record given a thread id passed in ID.  If
>> +   GET_CONTEXT is not 0, then also retrieve the context for this
>> +   thread.  If GET_CONTEXT is negative, then don't suspend the
>> +   thread.  */
> 
> I don't see any reason to capitalize get_context in the comment.
> 

That's what the GNU coding standards prefer:

[5.2 Commenting Your Work]
"The comment on a function is much clearer if you use the argument
names to speak about the argument values.  The variable name
itself should be lower case, but write it in upper case when
you are speaking about the value rather than the variable
itself.  Thus, “the node number NODE_NUM” rather than “an inode”."

In fact, I shouldn't be capitalizing ID.  Fixed that.

>> @@ -294,8 +304,7 @@ win32_add_thread (DWORD id, HANDLE h)
>>       th->context.Dr1 = dr[1];
>>       th->context.Dr2 = dr[2];
>>       th->context.Dr3 = dr[3];
>> -      /* th->context.Dr6 = dr[6];
>> -      FIXME: should we set dr6 also ?? */
>> +      th->context.Dr6 = 0xffff0ff0;
> 
> This, and similar cases, needs to use a #define with an explanatory comment.
> 
> With the above minor changes, this looks ok.
> 

Added a #define and checked in (see attached).

> I have to ask, however, if the SuspendThread's are even needed at all.
> When I was writing this code, I wasn't entirely sure that gdb needed to
> do anything like this but I erred on the side of caution.  So, I'm
> wondering if things would still work ok if the
> SuspendThread/ResumeThread stuff was gone.
> 

I wonder that too.  The docs say that we must not retrieve a thread
context while the thread is running.  When the inferior is stopped due
to a debug event the whole process is frozen, so in that case it should
safe.  I can give it a try later on, but it may take me a while to
confirm if it really is safe, especially because I currently only
have access to Windows XP SP2 and WinCE  (from the archives, I
get the impression Win2000 is pickier.)

OTOH, we'll still need to suspend threads if we want
to implement support for debugging one thread while the
others are running, or to step just one thread while
the others are stopped, or if we want to support stopping the
inferior without relying on a console available to handle
GenerateConsoleCtrlEvent; but these are different stories.

-- 
Pedro Alves



[-- Attachment #2: suspend_count_fix_plus_watchpoints.diff --]
[-- Type: text/x-diff, Size: 5503 bytes --]

2007-11-24  Pedro Alves  <pedro_alves@portugalmail.pt>

	* win32-nat.c (DR6_CLEAR_VALUE): New define.
	(thread_info_struct): Rename suspend_count to suspended, to be
	used as a flag.
	(thread_rec): Only suspend the thread if it wasn't suspended by
	gdb before.  Warn if suspending failed.
	(win32_add_thread): Set Dr6 to DR6_CLEAR_VALUE.
	(win32_continue): Set Dr6 to DR6_CLEAR_VALUE.  Update usage of the
	`suspended' flag.  Do ContinueDebugEvent after resuming the
	suspended threads, not before.  Set threads' contexts before
	resuming them, not after.
	(win32_resume): Set Dr6 to DR6_CLEAR_VALUE.

---
 gdb/win32-nat.c |   80 +++++++++++++++++++++++++++++++-------------------------
 1 file changed, 45 insertions(+), 35 deletions(-)

Index: src/gdb/win32-nat.c
===================================================================
--- src.orig/gdb/win32-nat.c	2007-11-24 11:44:14.000000000 +0000
+++ src/gdb/win32-nat.c	2007-11-24 11:44:56.000000000 +0000
@@ -91,6 +91,7 @@ enum
 static unsigned dr[8];
 static int debug_registers_changed;
 static int debug_registers_used;
+#define DR6_CLEAR_VALUE 0xffff0ff0
 
 /* The string sent by cygwin when it processes a signal.
    FIXME: This should be in a cygwin include file. */
@@ -112,14 +113,14 @@ static enum target_signal last_sig = TAR
 /* Set if a signal was received from the debugged process */
 
 /* Thread information structure used to track information that is
-   not available in gdb's thread structure. */
+   not available in gdb's thread structure.  */
 typedef struct thread_info_struct
   {
     struct thread_info_struct *next;
     DWORD id;
     HANDLE h;
     char *name;
-    int suspend_count;
+    int suspended;
     int reload_context;
     CONTEXT context;
     STACKFRAME sf;
@@ -244,9 +245,9 @@ check (BOOL ok, const char *file, int li
 		     GetLastError ());
 }
 
-/* Find a thread record given a thread id.
-   If get_context then also retrieve the context for this
-   thread. */
+/* Find a thread record given a thread id.  If GET_CONTEXT is not 0,
+   then also retrieve the context for this thread.  If GET_CONTEXT is
+   negative, then don't suspend the thread.  */
 static thread_info *
 thread_rec (DWORD id, int get_context)
 {
@@ -255,12 +256,21 @@ thread_rec (DWORD id, int get_context)
   for (th = &thread_head; (th = th->next) != NULL;)
     if (th->id == id)
       {
-	if (!th->suspend_count && get_context)
+	if (!th->suspended && get_context)
 	  {
 	    if (get_context > 0 && id != current_event.dwThreadId)
-	      th->suspend_count = SuspendThread (th->h) + 1;
+	      {
+		if (SuspendThread (th->h) == (DWORD) -1)
+		  {
+		    DWORD err = GetLastError ();
+		    warning (_("SuspendThread failed. (winerr %d)"),
+			     (int) err);
+		    return NULL;
+		  }
+		th->suspended = 1;
+	      }
 	    else if (get_context < 0)
-	      th->suspend_count = -1;
+	      th->suspended = -1;
 	    th->reload_context = 1;
 	  }
 	return th;
@@ -294,8 +304,7 @@ win32_add_thread (DWORD id, HANDLE h)
       th->context.Dr1 = dr[1];
       th->context.Dr2 = dr[2];
       th->context.Dr3 = dr[3];
-      /* th->context.Dr6 = dr[6];
-      FIXME: should we set dr6 also ?? */
+      th->context.Dr6 = DR6_CLEAR_VALUE;
       th->context.Dr7 = dr[7];
       CHECK (SetThreadContext (th->h, &th->context));
       th->context.ContextFlags = 0;
@@ -1122,32 +1131,34 @@ win32_continue (DWORD continue_status, i
 		  current_event.dwProcessId, current_event.dwThreadId,
 		  continue_status == DBG_CONTINUE ?
 		  "DBG_CONTINUE" : "DBG_EXCEPTION_NOT_HANDLED"));
+
+  for (th = &thread_head; (th = th->next) != NULL;)
+    if ((id == -1 || id == (int) th->id)
+	&& th->suspended)
+      {
+	if (debug_registers_changed)
+	  {
+	    th->context.ContextFlags |= CONTEXT_DEBUG_REGISTERS;
+	    th->context.Dr0 = dr[0];
+	    th->context.Dr1 = dr[1];
+	    th->context.Dr2 = dr[2];
+	    th->context.Dr3 = dr[3];
+	    th->context.Dr6 = DR6_CLEAR_VALUE;
+	    th->context.Dr7 = dr[7];
+	  }
+	if (th->context.ContextFlags)
+	  {
+	    CHECK (SetThreadContext (th->h, &th->context));
+	    th->context.ContextFlags = 0;
+	  }
+	if (th->suspended > 0)
+	  (void) ResumeThread (th->h);
+	th->suspended = 0;
+      }
+
   res = ContinueDebugEvent (current_event.dwProcessId,
 			    current_event.dwThreadId,
 			    continue_status);
-  if (res)
-    for (th = &thread_head; (th = th->next) != NULL;)
-      if (((id == -1) || (id == (int) th->id)) && th->suspend_count)
-	{
-
-	  for (i = 0; i < th->suspend_count; i++)
-	    (void) ResumeThread (th->h);
-	  th->suspend_count = 0;
-	  if (debug_registers_changed)
-	    {
-	      /* Only change the value of the debug registers */
-	      th->context.ContextFlags = CONTEXT_DEBUG_REGISTERS;
-	      th->context.Dr0 = dr[0];
-	      th->context.Dr1 = dr[1];
-	      th->context.Dr2 = dr[2];
-	      th->context.Dr3 = dr[3];
-	      /* th->context.Dr6 = dr[6];
-		 FIXME: should we set dr6 also ?? */
-	      th->context.Dr7 = dr[7];
-	      CHECK (SetThreadContext (th->h, &th->context));
-	      th->context.ContextFlags = 0;
-	    }
-	}
 
   debug_registers_changed = 0;
   return res;
@@ -1233,8 +1244,7 @@ win32_resume (ptid_t ptid, int step, enu
 	      th->context.Dr1 = dr[1];
 	      th->context.Dr2 = dr[2];
 	      th->context.Dr3 = dr[3];
-	      /* th->context.Dr6 = dr[6];
-	       FIXME: should we set dr6 also ?? */
+	      th->context.Dr6 = DR6_CLEAR_VALUE;
 	      th->context.Dr7 = dr[7];
 	    }
 	  CHECK (SetThreadContext (th->h, &th->context));



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

* Re: [win32] Fix suspend count handling
  2007-11-23 18:30                 ` Lerele
@ 2007-11-24 12:43                   ` Pedro Alves
  2007-11-24 14:21                     ` Lerele
  0 siblings, 1 reply; 28+ messages in thread
From: Pedro Alves @ 2007-11-24 12:43 UTC (permalink / raw)
  To: Lerele; +Cc: gdb-patches

Lerele wrote:

> 
> I'd also like to ask you a question, concerning a comment from Pedro 
> several messages back that has stayed around in my mind since then.
> 
> It's not related with this specific thread title, but since it's 
> gdbserver/win32 related, I haven't found appropriate to open a new 
> thread just for this simple question.
> 
> The issue is near the end of:
> http://sourceware.org/ml/gdb-patches/2007-11/msg00041.html
> 
> It's about the fact of gdb win32-nat.c some time ago having the 
> interrupt functionality similar to the one that has been recently 
> implemented using SuspendThread (versus using DebugBreak kind of 
> functions). Pedro commented back then that win32-nat.c did have sometime 
> in the past a similar implementation [that must have been dropped].
> Do you know/remember if it was dropped for a specific reason?
> 

Humm, I guess I mistaked win32-nat.c for the winpdo-nat.c
files on Apple's gdb:

See in:
http://www.opensource.apple.com/darwinsource/tarballs/other/gdb-186.1.tar.gz

In src/gdb-next/winpdo-nat.c, you'll see a SuspendThreads mechanism.
The file header states 1996 as the latest copyright year, but they
may have easilly failed to update it.  I'm not sure if win32-nat
ever had this mechanism, or if it was only added by Apple.  Our
cvs history only goes back till 1999.

I did say: "I *think* that if...".  :-)

-- 
Pedro Alves



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

* Re: [win32] Fix suspend count handling
  2007-11-24  5:33                 ` Christopher Faylor
@ 2007-11-24 14:18                   ` Lerele
  2007-11-24 15:49                     ` Pedro Alves
  2007-11-24 20:48                     ` Christopher Faylor
  0 siblings, 2 replies; 28+ messages in thread
From: Lerele @ 2007-11-24 14:18 UTC (permalink / raw)
  To: gdb-patches

Christopher Faylor escribió:
> On Fri, Nov 23, 2007 at 11:19:14AM +0100, Lerele wrote:
>   
>> Christopher Faylor escribi?:
>>     
>>> On Wed, Nov 21, 2007 at 11:18:38PM +0000, Pedro Alves wrote:
>>>   
>>>       
>>>> Pedro Alves wrote:
>>>>     
>>>>         
>>>>> Pedro Alves wrote:
>>>>>       
>>>>>           
>>>>>> On Nov 21, 2007 2:13 PM, Pierre Muller wrote:
>>>>>> That's not what I see here.  Can you show me a run where you get 4
>>>>>> only this patch applied?
>>>>>>
>>>>>>         
>>>>>>             
>>>>> I did try that, but posted a log of not doing it :-).
>>>>> I've just tried about 30 times, and only once I did see
>>>>> a 4 coming out ...  oh, well, one of those things.
>>>>>       
>>>>>           
>>>> OK.  Back at my home laptop, I can reproduce that with
>>>> no problems.  Let me clarify what the 4 problem really is.
>>>> It's a race between gdb and the inferior.
>>>>
>>>> Take this slightly changed test case.  The only difference
>>>> to the original version is the extra Sleep call.
>>>>
>>>> #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;
>>>>         }
>>>>
>>>>     Sleep (300);
>>>>
>>>>     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;
>>>> }
>>>>
>>>> If you do the "break at ...", "run", "thread 3", "continue"
>>>> sequence, and "..." is the "Sleep" line, you'll get 3,
>>>> but if you put the break at the /* set breakpoint here */
>>>> line, you'll get 4 (if you're (un)lucky).
>>>>
>>>> The race happens due to the fact that gdb is
>>>> doing something similar to this:
>>>>
>>>> win32_continue()
>>>> {
>>>>    ContinueDebugEvent (...);  /* Resumes all non suspended
>>>>                                  threads of the process.  */
>>>>
>>>>    /* At this point, gdb is running concurrently with
>>>>       the inferior threads that were not suspended - which
>>>>       included the main thread of the testcase.  */
>>>>    foreach t in threads do
>>>>       if t is suspended
>>>>          ResumeThread t
>>>>       fi
>>>>    done
>>>> }
>>>>
>>>> If you break at the Sleep call, when we resume, gdb will
>>>> have a bit of time to call ResumeThread on the suspended
>>>> thread of the testcase.  If you instead break at the
>>>> ResumeThread line, you'll have a good chance that the
>>>> inferior wins the race, hence the "4" result (remember
>>>> that ResumeThread returns the previous suspend count).
>>>> If we put something like this after the ResumeThread call:
>>>>
>>>>     (...)
>>>>     suspend_count = ResumeThread (h); /* set breakpoint here */
>>>>
>>>> +  Sleep (300);
>>>> +  SuspendThread (h);
>>>> +  suspend_count = ResumeThread (h);
>>>>
>>>>     printf ("%lu\n", suspend_count); /* should be 3 */
>>>>     (...)
>>>>
>>>> ... you'll see that eventually gdb will bring the
>>>> suspend count back to 3.  (A SuspendThread, ResumeThread
>>>> pair is the way to get at the suspend count.)
>>>>
>>>>     
>>>>         
>>>>> Since the watchpoint patch should fix this, what shall I do?  Shall I 
>>>>> merge
>>>>> the two and resubmit, or leave it at that ?  They've already been tested
>>>>> together without regressions.
>>>>>       
>>>>>           
>>>> Here is the merge from the patch I posted at the start of the
>>>> thread with this patch:
>>>>    [win32] Fix watchpoint support
>>>>    http://sourceware.org/ml/gdb-patches/2007-11/msg00390.html
>>>>
>>>> This patch fixes both the suspend_count
>>>> handling, and the watchpoint support.
>>>>
>>>> Thanks Pierre, for looking at it.
>>>>
>>>> OK ?
>>>>
>>>> -- 
>>>> Pedro Alves
>>>>     
>>>>         
>>>   
>>>       
>>>> 2007-11-21  Pedro Alves  <pedro_alves@portugalmail.pt>
>>>>
>>>> 	* win32-nat.c (thread_info_struct): Rename suspend_count to
>>>> 	suspended, to be used as a flag.
>>>> 	(thread_rec): Only suspend the thread if it wasn't suspended by
>>>> 	gdb before.  Warn if suspending failed.
>>>> 	(win32_add_thread): Set Dr6 to 0xffff0ff0.
>>>> 	(win32_resume): Likewise.
>>>> 	(win32_continue): Set Dr6 to 0xffff0ff0.  Update usage of the
>>>> 	`suspended' flag.  Do ContinueDebugEvent after resuming the
>>>> 	suspended threads, not before.  Set threads' contexts before
>>>> 	resuming them, not after.
>>>>     
>>>>         
>>>   
>>>       
>>>> ---
>>>> gdb/win32-nat.c |   80 
>>>> +++++++++++++++++++++++++++++++-------------------------
>>>> 1 file changed, 45 insertions(+), 35 deletions(-)
>>>>
>>>> Index: src/gdb/win32-nat.c
>>>> ===================================================================
>>>> --- src.orig/gdb/win32-nat.c	2007-11-11 23:13:04.000000000 +0000
>>>> +++ src/gdb/win32-nat.c	2007-11-21 22:39:56.000000000 +0000
>>>> @@ -112,14 +112,14 @@ static enum target_signal last_sig = TAR
>>>> /* Set if a signal was received from the debugged process */
>>>>
>>>> /* Thread information structure used to track information that is
>>>> -   not available in gdb's thread structure. */
>>>> +   not available in gdb's thread structure.  */
>>>> typedef struct thread_info_struct
>>>>   {
>>>>     struct thread_info_struct *next;
>>>>     DWORD id;
>>>>     HANDLE h;
>>>>     char *name;
>>>> -    int suspend_count;
>>>> +    int suspended;
>>>>     int reload_context;
>>>>     CONTEXT context;
>>>>     STACKFRAME sf;
>>>> @@ -244,9 +244,10 @@ check (BOOL ok, const char *file, int li
>>>> 		     GetLastError ());
>>>> }
>>>>
>>>> -/* Find a thread record given a thread id.
>>>> -   If get_context then also retrieve the context for this
>>>> -   thread. */
>>>> +/* Find a thread record given a thread id passed in ID.  If
>>>> +   GET_CONTEXT is not 0, then also retrieve the context for this
>>>> +   thread.  If GET_CONTEXT is negative, then don't suspend the
>>>> +   thread.  */
>>>>     
>>>>         
>>> I don't see any reason to capitalize get_context in the comment.
>>>
>>>   
>>>       
>>>> static thread_info *
>>>> thread_rec (DWORD id, int get_context)
>>>> {
>>>> @@ -255,12 +256,21 @@ thread_rec (DWORD id, int get_context)
>>>>   for (th = &thread_head; (th = th->next) != NULL;)
>>>>     if (th->id == id)
>>>>       {
>>>> -	if (!th->suspend_count && get_context)
>>>> +	if (!th->suspended && get_context)
>>>> 	  {
>>>> 	    if (get_context > 0 && id != current_event.dwThreadId)
>>>> -	      th->suspend_count = SuspendThread (th->h) + 1;
>>>> +	      {
>>>> +		if (SuspendThread (th->h) == (DWORD) -1)
>>>> +		  {
>>>> +		    DWORD err = GetLastError ();
>>>> +		    warning (_("SuspendThread failed. (winerr %d)"),
>>>> +			     (int) err);
>>>> +		    return NULL;
>>>> +		  }
>>>> +		th->suspended = 1;
>>>> +	      }
>>>> 	    else if (get_context < 0)
>>>> -	      th->suspend_count = -1;
>>>> +	      th->suspended = -1;
>>>> 	    th->reload_context = 1;
>>>> 	  }
>>>> 	return th;
>>>> @@ -294,8 +304,7 @@ win32_add_thread (DWORD id, HANDLE h)
>>>>       th->context.Dr1 = dr[1];
>>>>       th->context.Dr2 = dr[2];
>>>>       th->context.Dr3 = dr[3];
>>>> -      /* th->context.Dr6 = dr[6];
>>>> -      FIXME: should we set dr6 also ?? */
>>>> +      th->context.Dr6 = 0xffff0ff0;
>>>>     
>>>>         
>>> This, and similar cases, needs to use a #define with an explanatory 
>>> comment.
>>>
>>> With the above minor changes, this looks ok.
>>>
>>> I have to ask, however, if the SuspendThread's are even needed at all.
>>> When I was writing this code, I wasn't entirely sure that gdb needed to
>>> do anything like this but I erred on the side of caution.  So, I'm
>>> wondering if things would still work ok if the
>>> SuspendThread/ResumeThread stuff was gone.
>>>       
>> I think they are needed.  They were anyway with the new gdbserver based
>> (vs.  Win32 API based) interrupt code I sent several days ago, and that
>> so very kindly Pedro prepared for commitment, but that I still haven't
>> found the time to sit down and look at them (however I'm absolutely
>> sure they're just fine), I guess his changes must be similar to what I
>> sent in the first place.
>>     
>
> *Why* did you think you needed them in gdbserver?  Did you actually try
> not using them or did you just copy my code from win32-nat.c?
>
>   

I thought it natural to implement win32 functionality into gdbserver not 
starting from scratch, but from an already working implementation, such 
as win32-nat.c, however *truly* one drawback of this is that original 
code bugs got inherited into new implementation (such as the subject in 
question), and the porting process however was not really as 
straightforward as copy/paste; certain amount of work was involved (a 
lot of debugging gdbserver and gdb themselves), however I did not stop 
to think that SuspendThread was not actually needed, as it was already 
there.

I like your previous statement "I wasn't entirely sure that gdb needed 
to do anything like this but I erred on the side of caution.", except 
for the "erred" part.
I think its not bad to, in order to access thread data, lower memory, 
etc., first make sure it is actually paused, for whatever operation you 
want to do with it, as to not rely on a debug exception being received, 
or gdbserver itself stopping the low.  Also you may even need this 
functionality for any future new requirement.

If it works without problems and it's safer and more flexible, I'd just 
leave it. :-)



>> Apart from this, there's also the case where (at least for gdbserver) 
>> socket data is received asynchronously while the child is running. This 
>> socket data could indicate gdbserver to set/enable/disable a breakpoint, 
>> read thread registers, etc., and this kind of things may require to stop 
>> the child using SuspendThread.
>> Right?
>>     
>
> I don't know exactly what you are referring to but if you are proposing
> using SuspendThread/ResumeThread to work around non UNIX-like handling
> of signals, I've previously mentioned that the use of SuspendThread is
> dangerous since, the last I checked, Windows wasn't very good about not
> avoiding reentracy problems if you suspend a thread and then use another
> funcion from the Windows API.  This used to cause strange random
> behavior and even blue screens in older versions of Windows NT.  I guess
> it's possible that it's better these days but there is no way to really
> know for sure.
>
> cgf
>
>   


So then that's the reason.
Yes, I was referring to what you understood.

I do use win32 gdbserver quite often, and I have not encountered *any* 
kind of problem yet, however I do have to say I do use XP almost 
exclusively to run gdbserver.
If there is a problem with some other version of Windows, maybe you're 
right and SuspendThread should be removed after all.
It is a dilemma.

However, I guess you may have stumbled upon the fact that say for 
example msvcmon inferior *pausing* does actually work quite well, no 
matter what Windows version it's running on.  It's not that I want to 
start a discussion for mentioning that specific debugger nor writing ms 
here, but my opinion is that I think people would expect that kind of 
working from gdb/gdbserver on windows.  I would anyway.  This paragraph 
makes me ask, maybe the problems you talk about were due to some other 
reason, and not just about using SuspendThread only? Or are you 100% 
sure it's because of that specific function?

Leo.



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

* Re: [win32] Fix suspend count handling
  2007-11-24 12:43                   ` Pedro Alves
@ 2007-11-24 14:21                     ` Lerele
  0 siblings, 0 replies; 28+ messages in thread
From: Lerele @ 2007-11-24 14:21 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

Pedro Alves escribió:
> Lerele wrote:
>
>>
>> I'd also like to ask you a question, concerning a comment from Pedro 
>> several messages back that has stayed around in my mind since then.
>>
>> It's not related with this specific thread title, but since it's 
>> gdbserver/win32 related, I haven't found appropriate to open a new 
>> thread just for this simple question.
>>
>> The issue is near the end of:
>> http://sourceware.org/ml/gdb-patches/2007-11/msg00041.html
>>
>> It's about the fact of gdb win32-nat.c some time ago having the 
>> interrupt functionality similar to the one that has been recently 
>> implemented using SuspendThread (versus using DebugBreak kind of 
>> functions). Pedro commented back then that win32-nat.c did have 
>> sometime in the past a similar implementation [that must have been 
>> dropped].
>> Do you know/remember if it was dropped for a specific reason?
>>
>
> Humm, I guess I mistaked win32-nat.c for the winpdo-nat.c
> files on Apple's gdb:
>
> See in:
> http://www.opensource.apple.com/darwinsource/tarballs/other/gdb-186.1.tar.gz 
>
>
> In src/gdb-next/winpdo-nat.c, you'll see a SuspendThreads mechanism.
> The file header states 1996 as the latest copyright year, but they
> may have easilly failed to update it.  I'm not sure if win32-nat
> ever had this mechanism, or if it was only added by Apple.  Our
> cvs history only goes back till 1999.
>
> I did say: "I *think* that if...".  :-)
>

Sorry, I misunderstood "you'll see that once a similar method was used." 
as being an assertion.
Anyway there seems to be a reason not to SuspendThread, whether there 
was or wasn't such implementation in the past.

Leo.



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

* Re: [win32] Fix suspend count handling
  2007-11-24 14:18                   ` Lerele
@ 2007-11-24 15:49                     ` Pedro Alves
  2007-11-24 17:50                       ` Lerele
  2007-11-24 20:48                     ` Christopher Faylor
  1 sibling, 1 reply; 28+ messages in thread
From: Pedro Alves @ 2007-11-24 15:49 UTC (permalink / raw)
  To: Lerele; +Cc: gdb-patches

Lerele wrote:

 > This paragraph
> makes me ask, maybe the problems you talk about were due to some other 
> reason, and not just about using SuspendThread only? Or are you 100% 
> sure it's because of that specific function?
> 

Its not the function per se that's the problem.  It's that when we
suspend a thread it may be holding some internal lock, or
some such.  Calling the same function or another function that accesses
the same internal resources from another thread may violate what
was expected internally.  My experience on porting gdbserver to WinCE,
showed me that on WinCE at least, SuspendThread will not immediatelly
suspend the thread -- that probably means that the OS only stops the
threads on safe points.  That a look here [1].  It may be that
earlier versions of Windows had bugs that made that unsafe.
(Windows CE source code is available, but I won't touch it with a
ten-meter [2] pole.)


[1]
http://sourceware.org/ml/gdb-patches/2007-11/msg00220.html
-- Yes not perfect, I know.

[2]
I think metric.

-- 
Pedro Alves


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

* Re: [win32] Fix suspend count handling
  2007-11-24 15:49                     ` Pedro Alves
@ 2007-11-24 17:50                       ` Lerele
  2007-11-24 20:49                         ` Christopher Faylor
  0 siblings, 1 reply; 28+ messages in thread
From: Lerele @ 2007-11-24 17:50 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

Pedro Alves escribió:
> Lerele wrote:
>
> > This paragraph
>> makes me ask, maybe the problems you talk about were due to some 
>> other reason, and not just about using SuspendThread only? Or are you 
>> 100% sure it's because of that specific function?
>>
>
> Its not the function per se that's the problem.  It's that when we
> suspend a thread it may be holding some internal lock, or
> some such.  Calling the same function or another function that accesses
> the same internal resources from another thread may violate what
> was expected internally.  My experience on porting gdbserver to WinCE,
> showed me that on WinCE at least, SuspendThread will not immediatelly
> suspend the thread -- that probably means that the OS only stops the
> threads on safe points.  That a look here [1].  It may be that
> earlier versions of Windows had bugs that made that unsafe.
> (Windows CE source code is available, but I won't touch it with a
> ten-meter [2] pole.)
>
>
> [1]
> http://sourceware.org/ml/gdb-patches/2007-11/msg00220.html
> -- Yes not perfect, I know.
>
> [2]
> I think metric.
>

It's actually hard to believe those functions do not work as expected, 
especially because MSDN docs specifically state using SuspendThread 
before GetThreadContext, asuming the latter should work after the 
former, but of course anything is possible.

If that is true, it's useless of course to use them functions.




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

* Re: [win32] Fix suspend count handling
  2007-11-24 14:18                   ` Lerele
  2007-11-24 15:49                     ` Pedro Alves
@ 2007-11-24 20:48                     ` Christopher Faylor
  2007-11-25 14:44                       ` Lerele
  1 sibling, 1 reply; 28+ messages in thread
From: Christopher Faylor @ 2007-11-24 20:48 UTC (permalink / raw)
  To: Lerele, gdb-patches

On Sat, Nov 24, 2007 at 03:18:42PM +0100, Lerele wrote:
>>> Christopher Faylor escribi?:
>>>> I have to ask, however, if the SuspendThread's are even needed at all.
>>>> When I was writing this code, I wasn't entirely sure that gdb needed to
>>>> do anything like this but I erred on the side of caution.  So, I'm
>>>> wondering if things would still work ok if the
>>>> SuspendThread/ResumeThread stuff was gone.
>>>>       
>>> I think they are needed.  They were anyway with the new gdbserver based
>>> (vs.  Win32 API based) interrupt code I sent several days ago, and that
>>> so very kindly Pedro prepared for commitment, but that I still haven't
>>> found the time to sit down and look at them (however I'm absolutely
>>> sure they're just fine), I guess his changes must be similar to what I
>>> sent in the first place.
>>>     
>>
>> *Why* did you think you needed them in gdbserver?  Did you actually try
>> not using them or did you just copy my code from win32-nat.c?
>
> I thought it natural to implement win32 functionality into gdbserver not 
> starting from scratch, but from an already working implementation, such as 
> win32-nat.c, however *truly* one drawback of this is that original code 
> bugs got inherited into new implementation (such as the subject in 
> question), and the porting process however was not really as 
> straightforward as copy/paste; certain amount of work was involved (a lot 
> of debugging gdbserver and gdb themselves), however I did not stop to think 
> that SuspendThread was not actually needed, as it was already there.

So, in answer to my question about whether something was needed or not,
you asserted that it wasn't needed because you copied the code that I
wrote which was the source of my question.  Sorry but that doesn't really
answer my question.

If Windows already does the SuspendThread on all threads on debug event
then there is no reason to also do it in gdb.  I was asking if anyone
had actually checked if that was the case since it has been quite some
time since I did any experiments.

cgf


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

* Re: [win32] Fix suspend count handling
  2007-11-24 17:50                       ` Lerele
@ 2007-11-24 20:49                         ` Christopher Faylor
  0 siblings, 0 replies; 28+ messages in thread
From: Christopher Faylor @ 2007-11-24 20:49 UTC (permalink / raw)
  To: Lerele, Pedro Alves, gdb-patches

On Sat, Nov 24, 2007 at 06:50:39PM +0100, Lerele wrote:
> Pedro Alves escribi?:
>> Lerele wrote:
>>
>> > This paragraph
>>> makes me ask, maybe the problems you talk about were due to some other 
>>> reason, and not just about using SuspendThread only? Or are you 100% sure 
>>> it's because of that specific function?
>>>
>>
>> Its not the function per se that's the problem.  It's that when we
>> suspend a thread it may be holding some internal lock, or
>> some such.  Calling the same function or another function that accesses
>> the same internal resources from another thread may violate what
>> was expected internally.  My experience on porting gdbserver to WinCE,
>> showed me that on WinCE at least, SuspendThread will not immediatelly
>> suspend the thread -- that probably means that the OS only stops the
>> threads on safe points.  That a look here [1].  It may be that
>> earlier versions of Windows had bugs that made that unsafe.
>> (Windows CE source code is available, but I won't touch it with a
>> ten-meter [2] pole.)
>>
>>
>> [1]
>> http://sourceware.org/ml/gdb-patches/2007-11/msg00220.html
>> -- Yes not perfect, I know.
>>
>> [2]
>> I think metric.
>>
>
> It's actually hard to believe those functions do not work as expected, 
> especially because MSDN docs specifically state using SuspendThread before 
> GetThreadContext, asuming the latter should work after the former, but of 
> course anything is possible.
>
> If that is true, it's useless of course to use them functions.

It's possible that GetThreadContext may wait for pending SuspendThread's.

cgf


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

* Re: [win32] Fix suspend count handling
  2007-11-24 12:16               ` Pedro Alves
@ 2007-11-24 20:51                 ` Christopher Faylor
  0 siblings, 0 replies; 28+ messages in thread
From: Christopher Faylor @ 2007-11-24 20:51 UTC (permalink / raw)
  To: Pedro Alves, gdb-patches

On Sat, Nov 24, 2007 at 12:16:21PM +0000, Pedro Alves wrote:
> Added a #define and checked in (see attached).

Could you add a comment too at some point?  It's not clear to me
what that constant does.

cgf


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

* Re: [win32] Fix suspend count handling
  2007-11-24 20:48                     ` Christopher Faylor
@ 2007-11-25 14:44                       ` Lerele
  2007-11-25 18:13                         ` Christopher Faylor
  0 siblings, 1 reply; 28+ messages in thread
From: Lerele @ 2007-11-25 14:44 UTC (permalink / raw)
  To: Lerele, gdb-patches

Christopher Faylor escribió:
> On Sat, Nov 24, 2007 at 03:18:42PM +0100, Lerele wrote:
>   
>>>> Christopher Faylor escribi?:
>>>>         
>>>>> I have to ask, however, if the SuspendThread's are even needed at all.
>>>>> When I was writing this code, I wasn't entirely sure that gdb needed to
>>>>> do anything like this but I erred on the side of caution.  So, I'm
>>>>> wondering if things would still work ok if the
>>>>> SuspendThread/ResumeThread stuff was gone.
>>>>>       
>>>>>           
>>>> I think they are needed.  They were anyway with the new gdbserver based
>>>> (vs.  Win32 API based) interrupt code I sent several days ago, and that
>>>> so very kindly Pedro prepared for commitment, but that I still haven't
>>>> found the time to sit down and look at them (however I'm absolutely
>>>> sure they're just fine), I guess his changes must be similar to what I
>>>> sent in the first place.
>>>>     
>>>>         
>>> *Why* did you think you needed them in gdbserver?  Did you actually try
>>> not using them or did you just copy my code from win32-nat.c?
>>>       
>> I thought it natural to implement win32 functionality into gdbserver not 
>> starting from scratch, but from an already working implementation, such as 
>> win32-nat.c, however *truly* one drawback of this is that original code 
>> bugs got inherited into new implementation (such as the subject in 
>> question), and the porting process however was not really as 
>> straightforward as copy/paste; certain amount of work was involved (a lot 
>> of debugging gdbserver and gdb themselves), however I did not stop to think 
>> that SuspendThread was not actually needed, as it was already there.
>>     
>
> So, in answer to my question about whether something was needed or not,
> you asserted that it wasn't needed because you copied the code that I
> wrote which was the source of my question.  Sorry but that doesn't really
> answer my question.
>
>   
Sure I did, however the situation seems a bit more complicated.  I'll 
explain below.




> If Windows already does the SuspendThread on all threads on debug event
> then there is no reason to also do it in gdb.  I was asking if anyone
> had actually checked if that was the case since it has been quite some
> time since I did any experiments.
>
>   


What I said basically is that it is safer to leave the SuspendThread 
there as, besides being safer, it may be required for any future 
enhancement.
Also, upon reception of a Win32 debug event, calling SuspendThread 
should not do any harm, as the threads are already paused.
It is also the basis of the new interrupt method, which is SuspendThread 
based.


In my previous message, in the paragraph I wrote:

"Apart from this, there's also the case where (at least for gdbserver) 
socket data is received asynchronously while the child is running. This 
socket data could indicate gdbserver to set/enable/disable a breakpoint, 
read thread registers, etc., and this kind of things may require to stop 
the child using SuspendThread.
Right?"

I was refering a specific gdbserver functionality that for some reason 
is not currently working for current cvs gdbserver.
In fact right now I do not actually know for sure if this functionality 
ever worked for cvs gdb and got broken, or it is based on local 
modifications I have made to gdbserver.

Please let me clarify:

I have a gdbserver.exe version here that lets you set breakpoints into 
the child while the child is running (without having to interrupt the 
child --if you can, set breakpoint and continue the child).
For this functionality to work socket data availability check must be 
done somewhere in the WaitForDebugEvent loop/call trace.
I think however that what I did was have get_child_debug_event return a 
"spurious" signal periodically to have gdbserver check for this socket 
data and act accordingly to this received data.
The really important thing is that in this case, no Win32 debug event 
was received (and the child was still running), so when gdbserver wanted 
to access the thread, the thread_rec function was ultimately called, 
which itself calls SuspendThread.
So in this case calling SuspendThread *is* necessary.

Now as to the reason why this is not working, I think it's pointless to 
figure why I have a local gdbserver that asynchrounously lets you set 
breakpoints, or try figure out if some older official gdbserver version 
ever had this support.

It is not currently working, and I think it is a very nice feature, not 
only because it actually is useful, but also because people used to 
other debugging systems (such as msvcmon) are used to this.

I think it's best to have it working upstream, and for this, 
SuspendThread is mandatory.
What do you think?

Leo.




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

* Re: [win32] Fix suspend count handling
  2007-11-25 14:44                       ` Lerele
@ 2007-11-25 18:13                         ` Christopher Faylor
  2007-11-25 18:56                           ` Pedro Alves
  2007-11-25 20:34                           ` Lerele
  0 siblings, 2 replies; 28+ messages in thread
From: Christopher Faylor @ 2007-11-25 18:13 UTC (permalink / raw)
  To: gdb-patches

On Sun, Nov 25, 2007 at 03:44:31PM +0100, Lerele wrote:
> What do you think?

There is some code in win32-nat.c which was a result of my uncertainty
about the Windows debugging API.  I thought that since we have a couple
more eyes on this now someone might know a bit more about how this
works.  Understanding the foundations is never a bad idea.

I'm not interested in gdbserver or what you think may be happening in
the future.  If the SuspendThread/ResumeThread code can be eliminated
from win32-nat.c along with all of the bookkeeping that is required to
avoid races then it may be a good idea to do so.  Whether it is a good
idea in light of future enhancements is a decision I can make but,
personally, I rarely see a good reason to keep code complication around
for the future unless someone is actually planning to do the work.

We can stop talking about this now since it is apparent that no one
actually knows the answer to my question.

cgf


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

* Re: [win32] Fix suspend count handling
  2007-11-25 18:13                         ` Christopher Faylor
@ 2007-11-25 18:56                           ` Pedro Alves
  2007-11-25 22:05                             ` Christopher Faylor
  2007-11-25 20:34                           ` Lerele
  1 sibling, 1 reply; 28+ messages in thread
From: Pedro Alves @ 2007-11-25 18:56 UTC (permalink / raw)
  To: gdb-patches

Christopher Faylor wrote:
> On Sun, Nov 25, 2007 at 03:44:31PM +0100, Lerele wrote:
>> What do you think?
> 
> There is some code in win32-nat.c which was a result of my uncertainty
> about the Windows debugging API.  I thought that since we have a couple
> more eyes on this now someone might know a bit more about how this
> works.  Understanding the foundations is never a bad idea.
> 
> I'm not interested in gdbserver or what you think may be happening in
> the future.  If the SuspendThread/ResumeThread code can be eliminated
> from win32-nat.c along with all of the bookkeeping that is required to
> avoid races then it may be a good idea to do so.  Whether it is a good
> idea in light of future enhancements is a decision I can make but,
> personally, I rarely see a good reason to keep code complication around
> for the future unless someone is actually planning to do the work.
> 
> We can stop talking about this now since it is apparent that no one
> actually knows the answer to my question.
> 

100% Agreed.

Just to let you know that I plan on looking at this.
I'm specifically wanting to look at what we're doing
when/if we need to step over something with all
threads but the current stopped -- if that is supposed to
happen, it looks like we're broken, we should be
suspending all the threads but the current before
resuming.

-- 
Pedro Alves


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

* Re: [win32] Fix suspend count handling
  2007-11-25 18:13                         ` Christopher Faylor
  2007-11-25 18:56                           ` Pedro Alves
@ 2007-11-25 20:34                           ` Lerele
  1 sibling, 0 replies; 28+ messages in thread
From: Lerele @ 2007-11-25 20:34 UTC (permalink / raw)
  To: gdb-patches

Christopher Faylor escribió:
> On Sun, Nov 25, 2007 at 03:44:31PM +0100, Lerele wrote:
>   
>> What do you think?
>>     
>
> There is some code in win32-nat.c which was a result of my uncertainty
> about the Windows debugging API.  I thought that since we have a couple
> more eyes on this now someone might know a bit more about how this
> works.  Understanding the foundations is never a bad idea.
>
> I'm not interested in gdbserver or what you think may be happening in
> the future.  If the SuspendThread/ResumeThread code can be eliminated
> from win32-nat.c along with all of the bookkeeping that is required to
> avoid races then it may be a good idea to do so.  Whether it is a good
> idea in light of future enhancements is a decision I can make but,
> personally, I rarely see a good reason to keep code complication around
> for the future unless someone is actually planning to do the work.
>
> We can stop talking about this now since it is apparent that no one
> actually knows the answer to my question.
>
> cgf
>
>   

Okay.
Derived from my previous messages, which by the way I do not really know 
if you read/undestood, is that for the third time I'm saying 
SuspendThread I think is safer (as you did think once) and does not 
really hurt, and it's not such a complication keeping it around, in my 
opinion.
The only problem I see is that a small bug has been detected, that's all.

If win32-nat.c is going to give control back to gdb in response to a 
Win32 debug event only, it's obvious SuspendThread is not needed.
When WaitForDebugEvent returns an event, all child threads are stopped, 
so yes, SuspendThread is *not* needed.
Is this the short answer you were looking for???

Also, may you be interested in the fact that currently interrupting a 
running program using gdb 6.7 does *not* seem to work?  Either if you 
run gdb alone (not gdbserver) or using a front-end?
To my point, as gdbserver win32 code is win32-nat.c based, funtionality 
is very similar.  One such functionality could be the latest 
SuspendThread interruption that has been added to gdbserver (but not to 
win32-nat.c).  As such, could you be interested in this for win32-nat.c?
If this functionality is of interest, then that's another reason to keep 
thread_rec/SuspendThread.



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

* Re: [win32] Fix suspend count handling
  2007-11-25 18:56                           ` Pedro Alves
@ 2007-11-25 22:05                             ` Christopher Faylor
  2007-11-25 22:13                               ` Lerele
  0 siblings, 1 reply; 28+ messages in thread
From: Christopher Faylor @ 2007-11-25 22:05 UTC (permalink / raw)
  To: gdb-patches

On Sun, Nov 25, 2007 at 06:56:04PM +0000, Pedro Alves wrote:
> Christopher Faylor wrote:
>> On Sun, Nov 25, 2007 at 03:44:31PM +0100, Lerele wrote:
>>> What do you think?
>> There is some code in win32-nat.c which was a result of my uncertainty
>> about the Windows debugging API.  I thought that since we have a couple
>> more eyes on this now someone might know a bit more about how this
>> works.  Understanding the foundations is never a bad idea.
>> I'm not interested in gdbserver or what you think may be happening in
>> the future.  If the SuspendThread/ResumeThread code can be eliminated
>> from win32-nat.c along with all of the bookkeeping that is required to
>> avoid races then it may be a good idea to do so.  Whether it is a good
>> idea in light of future enhancements is a decision I can make but,
>> personally, I rarely see a good reason to keep code complication around
>> for the future unless someone is actually planning to do the work.
>> We can stop talking about this now since it is apparent that no one
>> actually knows the answer to my question.
>
> 100% Agreed.
>
> Just to let you know that I plan on looking at this.
> I'm specifically wanting to look at what we're doing
> when/if we need to step over something with all
> threads but the current stopped -- if that is supposed to
> happen, it looks like we're broken, we should be
> suspending all the threads but the current before
> resuming.

I was going to try just temporarily doing this to see what happens:

#define SuspendThread(hThread) 1
#define ResumeThread(hThread) 1

cgf


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

* Re: [win32] Fix suspend count handling
  2007-11-25 22:05                             ` Christopher Faylor
@ 2007-11-25 22:13                               ` Lerele
  0 siblings, 0 replies; 28+ messages in thread
From: Lerele @ 2007-11-25 22:13 UTC (permalink / raw)
  To: gdb-patches

Christopher Faylor escribió:
> On Sun, Nov 25, 2007 at 06:56:04PM +0000, Pedro Alves wrote:
>   
>> Christopher Faylor wrote:
>>     
>>> On Sun, Nov 25, 2007 at 03:44:31PM +0100, Lerele wrote:
>>>       
>>>> What do you think?
>>>>         
>>> There is some code in win32-nat.c which was a result of my uncertainty
>>> about the Windows debugging API.  I thought that since we have a couple
>>> more eyes on this now someone might know a bit more about how this
>>> works.  Understanding the foundations is never a bad idea.
>>> I'm not interested in gdbserver or what you think may be happening in
>>> the future.  If the SuspendThread/ResumeThread code can be eliminated
>>> from win32-nat.c along with all of the bookkeeping that is required to
>>> avoid races then it may be a good idea to do so.  Whether it is a good
>>> idea in light of future enhancements is a decision I can make but,
>>> personally, I rarely see a good reason to keep code complication around
>>> for the future unless someone is actually planning to do the work.
>>> We can stop talking about this now since it is apparent that no one
>>> actually knows the answer to my question.
>>>       
>> 100% Agreed.
>>
>> Just to let you know that I plan on looking at this.
>> I'm specifically wanting to look at what we're doing
>> when/if we need to step over something with all
>> threads but the current stopped -- if that is supposed to
>> happen, it looks like we're broken, we should be
>> suspending all the threads but the current before
>> resuming.
>>     
>
> I was going to try just temporarily doing this to see what happens:
>
> #define SuspendThread(hThread) 1
> #define ResumeThread(hThread) 1
>
> cgf
>
>   

I did remove SuspendThread from gdbserver, before my last reply.
Did have to remove SuspendThreadInterrupt support too.
Worked Ok.
I guess win32-nat.c should be similar.




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

end of thread, other threads:[~2007-11-25 22:13 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-11-21  0:35 [win32] Fix suspend count handling Pedro Alves
2007-11-21 11:25 ` Pierre Muller
2007-11-21 13:43   ` Pedro Alves
2007-11-21 14:13     ` Pierre Muller
2007-11-21 15:08       ` Pedro Alves
2007-11-21 15:32         ` Pierre Muller
2007-11-21 18:19         ` Pedro Alves
2007-11-21 23:33           ` Pedro Alves
2007-11-22  9:19             ` Pierre Muller
2007-11-23  1:07             ` Christopher Faylor
2007-11-23 10:19               ` Lerele
2007-11-23 18:30                 ` Lerele
2007-11-24 12:43                   ` Pedro Alves
2007-11-24 14:21                     ` Lerele
2007-11-24  5:33                 ` Christopher Faylor
2007-11-24 14:18                   ` Lerele
2007-11-24 15:49                     ` Pedro Alves
2007-11-24 17:50                       ` Lerele
2007-11-24 20:49                         ` Christopher Faylor
2007-11-24 20:48                     ` Christopher Faylor
2007-11-25 14:44                       ` Lerele
2007-11-25 18:13                         ` Christopher Faylor
2007-11-25 18:56                           ` Pedro Alves
2007-11-25 22:05                             ` Christopher Faylor
2007-11-25 22:13                               ` Lerele
2007-11-25 20:34                           ` Lerele
2007-11-24 12:16               ` Pedro Alves
2007-11-24 20:51                 ` Christopher Faylor

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox