[RFA/commit] (Windows) remove thread notification for main thread of inferior

Message ID 20190210132204.6139-1-brobecker@adacore.com
State New
Headers show
Series
  • [RFA/commit] (Windows) remove thread notification for main thread of inferior
Related show

Commit Message

Joel Brobecker Feb. 10, 2019, 1:22 p.m.
[this is a followup patch I said I had on Jan 5th and that I would
leave in "observation" in AdaCore's testing environment for a bit,
https://www.sourceware.org/ml/gdb-patches/2019-01/msg00075.html]

Hello,

This is a followup on a recent patch which, among other things
introduced the exit notification of the main thread in order
to be symetrical with the fact that a thread notification was
emitted before signaling its creation.

This patch takes the opposite approach of removing both creation
and exit notifications for that main thread, which is consistent
with what is done on other platforms such as GNU/Linux for instance.

gdb/ChangeLog

	* windows-nat.c (windows_add_thread): Add new parameter
	"main_thread_p" with default value set to false.  Update
	function documentation.
	(windows_delete_thread): Likewise.
	(fake_create_process): Update call to windows_add_thread
	to pass "main_thread_p" set to true.
	(get_windows_debug_event) <CREATE_PROCESS_DEBUG_EVENT>:
	Likewise.
	<EXIT_PROCESS_DEBUG_EVENT>: Update call to windows_delete_thread
	to pass "main_thread_p" set to true.

Tested on x86-windows (MinGW) using AdaCore's testsuite.  OK to apply?

Thanks,
-- 
Joel

---
 gdb/windows-nat.c | 68 ++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 52 insertions(+), 16 deletions(-)

-- 
2.17.1

Comments

Simon Marchi Feb. 11, 2019, 3:21 a.m. | #1
Hi Joel,

I didn't test, but this looks good to me.  Two small comments below.

> diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c

> index 2894b208f58..ae05d889a6a 100644

> --- a/gdb/windows-nat.c

> +++ b/gdb/windows-nat.c

> @@ -426,9 +426,17 @@ thread_rec (DWORD id, int get_context)

>    return NULL;

>  }

> 

> -/* Add a thread to the thread list.  */

> +/* Add a thread to the thread list.

> +

> +   PTID is the ptid of the thread to be deleted.

> +   H is its Windows handle.

> +   TLB is its thread local base.

> +   MAIN_THREAD_P should be true if the thread to be deleted is

> +   the main thread, false otherwise.  */


This comment about the function that adds threads talks about things to 
be deleted.

> +

>  static windows_thread_info *

> -windows_add_thread (ptid_t ptid, HANDLE h, void *tlb)

> +windows_add_thread (ptid_t ptid, HANDLE h, void *tlb,

> +		    bool main_thread_p = false)


Just a nit: in this case, where there are very few callers to update, I 
would opt for not using a default parameter value.  It's probably just a 
personal preference, but I find it clearer to have the explicit value at 
the call site.

Simon
Joel Brobecker Feb. 12, 2019, 11:25 a.m. | #2
Hi Simon,

> Hi Joel,

> 

> I didn't test, but this looks good to me.  Two small comments below.


Thanks for the review!

> > diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c

> > index 2894b208f58..ae05d889a6a 100644

> > --- a/gdb/windows-nat.c

> > +++ b/gdb/windows-nat.c

> > @@ -426,9 +426,17 @@ thread_rec (DWORD id, int get_context)

> >    return NULL;

> >  }

> > 

> > -/* Add a thread to the thread list.  */

> > +/* Add a thread to the thread list.

> > +

> > +   PTID is the ptid of the thread to be deleted.

> > +   H is its Windows handle.

> > +   TLB is its thread local base.

> > +   MAIN_THREAD_P should be true if the thread to be deleted is

> > +   the main thread, false otherwise.  */

> 

> This comment about the function that adds threads talks about things to be

> deleted.


Indeed. Fixed in the attached version.

> >  static windows_thread_info *

> > -windows_add_thread (ptid_t ptid, HANDLE h, void *tlb)

> > +windows_add_thread (ptid_t ptid, HANDLE h, void *tlb,

> > +		    bool main_thread_p = false)

> 

> Just a nit: in this case, where there are very few callers to update, I

> would opt for not using a default parameter value.  It's probably just a

> personal preference, but I find it clearer to have the explicit value at the

> call site.


It wasn't really the number of callers to update that prompted me to
use a default value, but rather the fact that, in the normal case,
that parameter is really redundant, at least as far as the reader's
understanding is concerned. This is related a bit to the fact that
I am partial to the option of being able to name parameters at the
point call, something that C++ doesn't support. This would have been
particularly useful in this case here, because I've always found
"true" or "false" litteral constants in function calls like that
to be rather mysterious. So much so that I felt I needed to add
a comment to name them that way. Since it felt like providing it
at the point of call when false was redundant, I decided against
providing its value.

The attached patch follows your suggestion nonetheless. I worked
around my concern the same way I did when passing the new parameter
as true, and so this is good for me.

gdb/ChangeLog

        * windows-nat.c (windows_add_thread): Add new parameter
        "main_thread_p" with default value set to false.  Update
        function documentation as well as all callers.
        (windows_delete_thread): Likewise.
        (fake_create_process): Update call to windows_add_thread.
        (get_windows_debug_event) <CREATE_THREAD_DEBUG_EVENT>
        <CREATE_PROCESS_DEBUG_EVENT>: Likewise.
        <EXIT_THREAD_DEBUG_EVENT, EXIT_PROCESS_DEBUG_EVENT>: Update
        call to windows_delete_thread.

Tested on x86-windows (MinGW) using AdaCore's testsuite.
OK to push?

Thanks!
-- 
Joel
From 83d8d40a71096c5138b5b41fc9ac365028d0b8c3 Mon Sep 17 00:00:00 2001
From: Joel Brobecker <brobecker@adacore.com>

Date: Tue, 12 Feb 2019 12:06:43 +0100
Subject: [PATCH] (Windows) remove thread notification for main thread of
 inferior

This is a followup on a recent patch which, among other things
introduced the exit notification of the main thread in order
to be symetrical with the fact that a thread notification was
emitted before signaling its creation.

This patch takes the opposite approach of removing both creation
and exit notifications for that main thread, which is consistent
with what is done on other platforms such as GNU/Linux for instance.

gdb/ChangeLog

	* windows-nat.c (windows_add_thread): Add new parameter
	"main_thread_p" with default value set to false.  Update
	function documentation as well as all callers.
	(windows_delete_thread): Likewise.
	(fake_create_process): Update call to windows_add_thread.
	(get_windows_debug_event) <CREATE_THREAD_DEBUG_EVENT>
	<CREATE_PROCESS_DEBUG_EVENT>: Likewise.
	<EXIT_THREAD_DEBUG_EVENT, EXIT_PROCESS_DEBUG_EVENT>: Update
	call to windows_delete_thread.

Tested on x86-windows (MinGW) using AdaCore's testsuite.
---
 gdb/windows-nat.c | 78 ++++++++++++++++++++++++++++++++++++++++---------------
 1 file changed, 57 insertions(+), 21 deletions(-)

diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c
index 2894b20..f0fc8ec 100644
--- a/gdb/windows-nat.c
+++ b/gdb/windows-nat.c
@@ -426,9 +426,16 @@ thread_rec (DWORD id, int get_context)
   return NULL;
 }
 
-/* Add a thread to the thread list.  */
+/* Add a thread to the thread list.
+
+   PTID is the ptid of the thread to be added.
+   H is its Windows handle.
+   TLB is its thread local base.
+   MAIN_THREAD_P should be true if the thread to be deleted is
+   the main thread, false otherwise.  */
+
 static windows_thread_info *
-windows_add_thread (ptid_t ptid, HANDLE h, void *tlb)
+windows_add_thread (ptid_t ptid, HANDLE h, void *tlb, bool main_thread_p)
 {
   windows_thread_info *th;
   DWORD id;
@@ -446,7 +453,17 @@ windows_add_thread (ptid_t ptid, HANDLE h, void *tlb)
   th->thread_local_base = (CORE_ADDR) (uintptr_t) tlb;
   th->next = thread_head.next;
   thread_head.next = th;
-  add_thread (ptid);
+
+  /* Add this new thread to the list of threads.
+
+     To be consistent with what's done on other platforms, we add
+     the main thread silently (in reality, this thread is really
+     more of a process to the user than a thread).  */
+  if (main_thread_p)
+    add_thread_silent (ptid);
+  else
+    add_thread (ptid);
+
   /* Set the debug registers for the new thread if they are used.  */
   if (debug_registers_used)
     {
@@ -483,9 +500,15 @@ windows_init_thread_list (void)
   thread_head.next = NULL;
 }
 
-/* Delete a thread from the list of threads.  */
+/* Delete a thread from the list of threads.
+
+   PTID is the ptid of the thread to be deleted.
+   EXIT_CODE is the thread's exit code.
+   MAIN_THREAD_P should be true if the thread to be deleted is
+   the main thread, false otherwise.  */
+
 static void
-windows_delete_thread (ptid_t ptid, DWORD exit_code)
+windows_delete_thread (ptid_t ptid, DWORD exit_code, bool main_thread_p)
 {
   windows_thread_info *th;
   DWORD id;
@@ -494,11 +517,19 @@ windows_delete_thread (ptid_t ptid, DWORD exit_code)
 
   id = ptid.tid ();
 
+  /* Emit a notification about the thread being deleted.
+
+     Note that no notification was printed when the main thread
+     was created, and thus, unless in verbose mode, we should be
+     symetrical, and avoid that notification for the main thread
+     here as well.  */
+
   if (info_verbose)
     printf_unfiltered ("[Deleting %s]\n", target_pid_to_str (ptid));
-  else if (print_thread_events)
+  else if (print_thread_events && !main_thread_p)
     printf_unfiltered (_("[%s exited with code %u]\n"),
 		       target_pid_to_str (ptid), (unsigned) exit_code);
+
   delete_thread (find_thread_ptid (ptid));
 
   for (th = &thread_head;
@@ -1375,11 +1406,12 @@ fake_create_process (void)
       /*  We can not debug anything in that case.  */
     }
   main_thread_id = current_event.dwThreadId;
-  current_thread = windows_add_thread (
-		     ptid_t (current_event.dwProcessId, 0,
-			     current_event.dwThreadId),
-		     current_event.u.CreateThread.hThread,
-		     current_event.u.CreateThread.lpThreadLocalBase);
+  current_thread
+    = windows_add_thread (ptid_t (current_event.dwProcessId, 0,
+				  current_event.dwThreadId),
+			  current_event.u.CreateThread.hThread,
+			  current_event.u.CreateThread.lpThreadLocalBase,
+			  true /* main_thread_p */);
   return main_thread_id;
 }
 
@@ -1548,10 +1580,11 @@ get_windows_debug_event (struct target_ops *ops,
 	}
       /* Record the existence of this thread.  */
       thread_id = current_event.dwThreadId;
-      th = windows_add_thread (ptid_t (current_event.dwProcessId, 0,
-				       current_event.dwThreadId),
-			     current_event.u.CreateThread.hThread,
-			     current_event.u.CreateThread.lpThreadLocalBase);
+      th = windows_add_thread
+        (ptid_t (current_event.dwProcessId, 0, current_event.dwThreadId),
+	 current_event.u.CreateThread.hThread,
+	 current_event.u.CreateThread.lpThreadLocalBase,
+	 false /* main_thread_p */);
 
       break;
 
@@ -1562,7 +1595,8 @@ get_windows_debug_event (struct target_ops *ops,
 		     "EXIT_THREAD_DEBUG_EVENT"));
       windows_delete_thread (ptid_t (current_event.dwProcessId, 0,
 				     current_event.dwThreadId),
-			     current_event.u.ExitThread.dwExitCode);
+			     current_event.u.ExitThread.dwExitCode,
+			     false /* main_thread_p */);
       th = &dummy_thread_info;
       break;
 
@@ -1578,10 +1612,12 @@ get_windows_debug_event (struct target_ops *ops,
       current_process_handle = current_event.u.CreateProcessInfo.hProcess;
       main_thread_id = current_event.dwThreadId;
       /* Add the main thread.  */
-      th = windows_add_thread (ptid_t (current_event.dwProcessId, 0,
-				       current_event.dwThreadId),
-	     current_event.u.CreateProcessInfo.hThread,
-	     current_event.u.CreateProcessInfo.lpThreadLocalBase);
+      th = windows_add_thread
+        (ptid_t (current_event.dwProcessId, 0,
+		 current_event.dwThreadId),
+	 current_event.u.CreateProcessInfo.hThread,
+	 current_event.u.CreateProcessInfo.lpThreadLocalBase,
+	 true /* main_thread_p */);
       thread_id = current_event.dwThreadId;
       break;
 
@@ -1601,7 +1637,7 @@ get_windows_debug_event (struct target_ops *ops,
 	{
 	  windows_delete_thread (ptid_t (current_event.dwProcessId, 0,
 					 main_thread_id),
-				 0);
+				 0, true /* main_thread_p */);
 	  ourstatus->kind = TARGET_WAITKIND_EXITED;
 	  ourstatus->value.integer = current_event.u.ExitProcess.dwExitCode;
 	  thread_id = main_thread_id;
-- 
2.8.3
Simon Marchi Feb. 12, 2019, 2 p.m. | #3
On 2019-02-12 06:25, Joel Brobecker wrote:
> Hi Simon,

> 

>> Hi Joel,

>> 

>> I didn't test, but this looks good to me.  Two small comments below.

> 

> Thanks for the review!

> 

>> > diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c

>> > index 2894b208f58..ae05d889a6a 100644

>> > --- a/gdb/windows-nat.c

>> > +++ b/gdb/windows-nat.c

>> > @@ -426,9 +426,17 @@ thread_rec (DWORD id, int get_context)

>> >    return NULL;

>> >  }

>> >

>> > -/* Add a thread to the thread list.  */

>> > +/* Add a thread to the thread list.

>> > +

>> > +   PTID is the ptid of the thread to be deleted.

>> > +   H is its Windows handle.

>> > +   TLB is its thread local base.

>> > +   MAIN_THREAD_P should be true if the thread to be deleted is

>> > +   the main thread, false otherwise.  */

>> 

>> This comment about the function that adds threads talks about things 

>> to be

>> deleted.

> 

> Indeed. Fixed in the attached version.

> 

>> >  static windows_thread_info *

>> > -windows_add_thread (ptid_t ptid, HANDLE h, void *tlb)

>> > +windows_add_thread (ptid_t ptid, HANDLE h, void *tlb,

>> > +		    bool main_thread_p = false)

>> 

>> Just a nit: in this case, where there are very few callers to update, 

>> I

>> would opt for not using a default parameter value.  It's probably just 

>> a

>> personal preference, but I find it clearer to have the explicit value 

>> at the

>> call site.

> 

> It wasn't really the number of callers to update that prompted me to

> use a default value, but rather the fact that, in the normal case,

> that parameter is really redundant, at least as far as the reader's

> understanding is concerned. This is related a bit to the fact that

> I am partial to the option of being able to name parameters at the

> point call, something that C++ doesn't support. This would have been

> particularly useful in this case here, because I've always found

> "true" or "false" litteral constants in function calls like that

> to be rather mysterious. So much so that I felt I needed to add

> a comment to name them that way. Since it felt like providing it

> at the point of call when false was redundant, I decided against

> providing its value.

> 

> The attached patch follows your suggestion nonetheless. I worked

> around my concern the same way I did when passing the new parameter

> as true, and so this is good for me.


Your rationale makes sense, I am fine with your original code too since 
you gave a good justification.  However you prefer.

I agree about the fact that literal values in function calls are often 
not that readable, and not only true/false.

> gdb/ChangeLog

> 

>         * windows-nat.c (windows_add_thread): Add new parameter

>         "main_thread_p" with default value set to false.  Update

>         function documentation as well as all callers.

>         (windows_delete_thread): Likewise.

>         (fake_create_process): Update call to windows_add_thread.

>         (get_windows_debug_event) <CREATE_THREAD_DEBUG_EVENT>

>         <CREATE_PROCESS_DEBUG_EVENT>: Likewise.

>         <EXIT_THREAD_DEBUG_EVENT, EXIT_PROCESS_DEBUG_EVENT>: Update

>         call to windows_delete_thread.

> 

> Tested on x86-windows (MinGW) using AdaCore's testsuite.

> OK to push?

> 

> Thanks!


There is still a mention of "deleted" in the windows_add_thread doc, 
otherwise LGTM.

Simon
Joel Brobecker Feb. 14, 2019, 3:15 a.m. | #4
> Your rationale makes sense, I am fine with your original code too since you

> gave a good justification.  However you prefer.

> 

> I agree about the fact that literal values in function calls are often not

> that readable, and not only true/false.


I went with what you suggested. Both are equally good, I think.

> > gdb/ChangeLog

> > 

> >         * windows-nat.c (windows_add_thread): Add new parameter

> >         "main_thread_p" with default value set to false.  Update

> >         function documentation as well as all callers.

> >         (windows_delete_thread): Likewise.

> >         (fake_create_process): Update call to windows_add_thread.

> >         (get_windows_debug_event) <CREATE_THREAD_DEBUG_EVENT>

> >         <CREATE_PROCESS_DEBUG_EVENT>: Likewise.

> >         <EXIT_THREAD_DEBUG_EVENT, EXIT_PROCESS_DEBUG_EVENT>: Update

> >         call to windows_delete_thread.

> > 

> > Tested on x86-windows (MinGW) using AdaCore's testsuite.

> > OK to push?

> > 

> > Thanks!

> 

> There is still a mention of "deleted" in the windows_add_thread doc,

> otherwise LGTM.


Argh! Talk about tunnel vision :-(. Fixed thusly, and pushed.

Thanks Simon.
-- 
Joel
From c559d7096b4b1b9c4e8d78cfd67b1892c1836ffb Mon Sep 17 00:00:00 2001
From: Joel Brobecker <brobecker@adacore.com>

Date: Thu, 14 Feb 2019 07:13:26 +0400
Subject: [PATCH] (Windows) remove thread notification for main thread of
 inferior

This is a followup on a recent patch which, among other things
introduced the exit notification of the main thread in order
to be symetrical with the fact that a thread notification was
emitted before signaling its creation.

This patch takes the opposite approach of removing both creation
and exit notifications for that main thread, which is consistent
with what is done on other platforms such as GNU/Linux for instance.

gdb/ChangeLog

	* windows-nat.c (windows_add_thread): Add new parameter
	"main_thread_p" with default value set to false.  Update
	function documentation as well as all callers.
	(windows_delete_thread): Likewise.
	(fake_create_process): Update call to windows_add_thread.
	(get_windows_debug_event) <CREATE_THREAD_DEBUG_EVENT>
	<CREATE_PROCESS_DEBUG_EVENT>: Likewise.
	<EXIT_THREAD_DEBUG_EVENT, EXIT_PROCESS_DEBUG_EVENT>: Update
	call to windows_delete_thread.

Tested on x86-windows (MinGW) using AdaCore's testsuite.
---
 gdb/ChangeLog     | 12 ++++++++
 gdb/windows-nat.c | 78 ++++++++++++++++++++++++++++++++++-------------
 2 files changed, 69 insertions(+), 21 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index ba505d3f260..0dec9b00c0d 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,15 @@
+2019-02-14  Joel Brobecker  <brobecker@adacore.com>
+
+	* windows-nat.c (windows_add_thread): Add new parameter
+	"main_thread_p" with default value set to false.  Update
+	function documentation as well as all callers.
+	(windows_delete_thread): Likewise.
+	(fake_create_process): Update call to windows_add_thread.
+	(get_windows_debug_event) <CREATE_THREAD_DEBUG_EVENT>
+	<CREATE_PROCESS_DEBUG_EVENT>: Likewise.
+	<EXIT_THREAD_DEBUG_EVENT, EXIT_PROCESS_DEBUG_EVENT>: Update
+	call to windows_delete_thread.
+
 2019-02-13  Simon Marchi  <simon.marchi@ericsson.com>
 
 	* MAINTAINERS: Add Andrew Burgess as global maintainer.
diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c
index 2894b208f58..e47fcb1b40a 100644
--- a/gdb/windows-nat.c
+++ b/gdb/windows-nat.c
@@ -426,9 +426,16 @@ thread_rec (DWORD id, int get_context)
   return NULL;
 }
 
-/* Add a thread to the thread list.  */
+/* Add a thread to the thread list.
+
+   PTID is the ptid of the thread to be added.
+   H is its Windows handle.
+   TLB is its thread local base.
+   MAIN_THREAD_P should be true if the thread to be added is
+   the main thread, false otherwise.  */
+
 static windows_thread_info *
-windows_add_thread (ptid_t ptid, HANDLE h, void *tlb)
+windows_add_thread (ptid_t ptid, HANDLE h, void *tlb, bool main_thread_p)
 {
   windows_thread_info *th;
   DWORD id;
@@ -446,7 +453,17 @@ windows_add_thread (ptid_t ptid, HANDLE h, void *tlb)
   th->thread_local_base = (CORE_ADDR) (uintptr_t) tlb;
   th->next = thread_head.next;
   thread_head.next = th;
-  add_thread (ptid);
+
+  /* Add this new thread to the list of threads.
+
+     To be consistent with what's done on other platforms, we add
+     the main thread silently (in reality, this thread is really
+     more of a process to the user than a thread).  */
+  if (main_thread_p)
+    add_thread_silent (ptid);
+  else
+    add_thread (ptid);
+
   /* Set the debug registers for the new thread if they are used.  */
   if (debug_registers_used)
     {
@@ -483,9 +500,15 @@ windows_init_thread_list (void)
   thread_head.next = NULL;
 }
 
-/* Delete a thread from the list of threads.  */
+/* Delete a thread from the list of threads.
+
+   PTID is the ptid of the thread to be deleted.
+   EXIT_CODE is the thread's exit code.
+   MAIN_THREAD_P should be true if the thread to be deleted is
+   the main thread, false otherwise.  */
+
 static void
-windows_delete_thread (ptid_t ptid, DWORD exit_code)
+windows_delete_thread (ptid_t ptid, DWORD exit_code, bool main_thread_p)
 {
   windows_thread_info *th;
   DWORD id;
@@ -494,11 +517,19 @@ windows_delete_thread (ptid_t ptid, DWORD exit_code)
 
   id = ptid.tid ();
 
+  /* Emit a notification about the thread being deleted.
+
+     Note that no notification was printed when the main thread
+     was created, and thus, unless in verbose mode, we should be
+     symetrical, and avoid that notification for the main thread
+     here as well.  */
+
   if (info_verbose)
     printf_unfiltered ("[Deleting %s]\n", target_pid_to_str (ptid));
-  else if (print_thread_events)
+  else if (print_thread_events && !main_thread_p)
     printf_unfiltered (_("[%s exited with code %u]\n"),
 		       target_pid_to_str (ptid), (unsigned) exit_code);
+
   delete_thread (find_thread_ptid (ptid));
 
   for (th = &thread_head;
@@ -1375,11 +1406,12 @@ fake_create_process (void)
       /*  We can not debug anything in that case.  */
     }
   main_thread_id = current_event.dwThreadId;
-  current_thread = windows_add_thread (
-		     ptid_t (current_event.dwProcessId, 0,
-			     current_event.dwThreadId),
-		     current_event.u.CreateThread.hThread,
-		     current_event.u.CreateThread.lpThreadLocalBase);
+  current_thread
+    = windows_add_thread (ptid_t (current_event.dwProcessId, 0,
+				  current_event.dwThreadId),
+			  current_event.u.CreateThread.hThread,
+			  current_event.u.CreateThread.lpThreadLocalBase,
+			  true /* main_thread_p */);
   return main_thread_id;
 }
 
@@ -1548,10 +1580,11 @@ get_windows_debug_event (struct target_ops *ops,
 	}
       /* Record the existence of this thread.  */
       thread_id = current_event.dwThreadId;
-      th = windows_add_thread (ptid_t (current_event.dwProcessId, 0,
-				       current_event.dwThreadId),
-			     current_event.u.CreateThread.hThread,
-			     current_event.u.CreateThread.lpThreadLocalBase);
+      th = windows_add_thread
+        (ptid_t (current_event.dwProcessId, 0, current_event.dwThreadId),
+	 current_event.u.CreateThread.hThread,
+	 current_event.u.CreateThread.lpThreadLocalBase,
+	 false /* main_thread_p */);
 
       break;
 
@@ -1562,7 +1595,8 @@ get_windows_debug_event (struct target_ops *ops,
 		     "EXIT_THREAD_DEBUG_EVENT"));
       windows_delete_thread (ptid_t (current_event.dwProcessId, 0,
 				     current_event.dwThreadId),
-			     current_event.u.ExitThread.dwExitCode);
+			     current_event.u.ExitThread.dwExitCode,
+			     false /* main_thread_p */);
       th = &dummy_thread_info;
       break;
 
@@ -1578,10 +1612,12 @@ get_windows_debug_event (struct target_ops *ops,
       current_process_handle = current_event.u.CreateProcessInfo.hProcess;
       main_thread_id = current_event.dwThreadId;
       /* Add the main thread.  */
-      th = windows_add_thread (ptid_t (current_event.dwProcessId, 0,
-				       current_event.dwThreadId),
-	     current_event.u.CreateProcessInfo.hThread,
-	     current_event.u.CreateProcessInfo.lpThreadLocalBase);
+      th = windows_add_thread
+        (ptid_t (current_event.dwProcessId, 0,
+		 current_event.dwThreadId),
+	 current_event.u.CreateProcessInfo.hThread,
+	 current_event.u.CreateProcessInfo.lpThreadLocalBase,
+	 true /* main_thread_p */);
       thread_id = current_event.dwThreadId;
       break;
 
@@ -1601,7 +1637,7 @@ get_windows_debug_event (struct target_ops *ops,
 	{
 	  windows_delete_thread (ptid_t (current_event.dwProcessId, 0,
 					 main_thread_id),
-				 0);
+				 0, true /* main_thread_p */);
 	  ourstatus->kind = TARGET_WAITKIND_EXITED;
 	  ourstatus->value.integer = current_event.u.ExitProcess.dwExitCode;
 	  thread_id = main_thread_id;
-- 
2.17.1

Patch

diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c
index 2894b208f58..ae05d889a6a 100644
--- a/gdb/windows-nat.c
+++ b/gdb/windows-nat.c
@@ -426,9 +426,17 @@  thread_rec (DWORD id, int get_context)
   return NULL;
 }
 
-/* Add a thread to the thread list.  */
+/* Add a thread to the thread list.
+
+   PTID is the ptid of the thread to be deleted.
+   H is its Windows handle.
+   TLB is its thread local base.
+   MAIN_THREAD_P should be true if the thread to be deleted is
+   the main thread, false otherwise.  */
+
 static windows_thread_info *
-windows_add_thread (ptid_t ptid, HANDLE h, void *tlb)
+windows_add_thread (ptid_t ptid, HANDLE h, void *tlb,
+		    bool main_thread_p = false)
 {
   windows_thread_info *th;
   DWORD id;
@@ -446,7 +454,17 @@  windows_add_thread (ptid_t ptid, HANDLE h, void *tlb)
   th->thread_local_base = (CORE_ADDR) (uintptr_t) tlb;
   th->next = thread_head.next;
   thread_head.next = th;
-  add_thread (ptid);
+
+  /* Add this new thread to the list of threads.
+
+     To be consistent with what's done on other platforms, we add
+     the main thread silently (in reality, this thread is really
+     more of a process to the user than a thread).  */
+  if (main_thread_p)
+    add_thread_silent (ptid);
+  else
+    add_thread (ptid);
+
   /* Set the debug registers for the new thread if they are used.  */
   if (debug_registers_used)
     {
@@ -483,9 +501,16 @@  windows_init_thread_list (void)
   thread_head.next = NULL;
 }
 
-/* Delete a thread from the list of threads.  */
+/* Delete a thread from the list of threads.
+
+   PTID is the ptid of the thread to be deleted.
+   EXIT_CODE is the thread's exit code.
+   MAIN_THREAD_P should be true if the thread to be deleted is
+   the main thread, false otherwise.  */
+
 static void
-windows_delete_thread (ptid_t ptid, DWORD exit_code)
+windows_delete_thread (ptid_t ptid, DWORD exit_code,
+		       bool main_thread_p = false)
 {
   windows_thread_info *th;
   DWORD id;
@@ -494,11 +519,19 @@  windows_delete_thread (ptid_t ptid, DWORD exit_code)
 
   id = ptid.tid ();
 
+  /* Emit a notification about the thread being deleted.
+
+     Note that no notification was printed when the main thread
+     was created, and thus, unless in verbose mode, we should be
+     symetrical, and avoid that notification for the main thread
+     here as well.  */
+
   if (info_verbose)
     printf_unfiltered ("[Deleting %s]\n", target_pid_to_str (ptid));
-  else if (print_thread_events)
+  else if (print_thread_events && !main_thread_p)
     printf_unfiltered (_("[%s exited with code %u]\n"),
 		       target_pid_to_str (ptid), (unsigned) exit_code);
+
   delete_thread (find_thread_ptid (ptid));
 
   for (th = &thread_head;
@@ -1375,11 +1408,12 @@  fake_create_process (void)
       /*  We can not debug anything in that case.  */
     }
   main_thread_id = current_event.dwThreadId;
-  current_thread = windows_add_thread (
-		     ptid_t (current_event.dwProcessId, 0,
-			     current_event.dwThreadId),
-		     current_event.u.CreateThread.hThread,
-		     current_event.u.CreateThread.lpThreadLocalBase);
+  current_thread
+    = windows_add_thread (ptid_t (current_event.dwProcessId, 0,
+				  current_event.dwThreadId),
+			  current_event.u.CreateThread.hThread,
+			  current_event.u.CreateThread.lpThreadLocalBase,
+			  true /* main_thread_p */);
   return main_thread_id;
 }
 
@@ -1578,10 +1612,12 @@  get_windows_debug_event (struct target_ops *ops,
       current_process_handle = current_event.u.CreateProcessInfo.hProcess;
       main_thread_id = current_event.dwThreadId;
       /* Add the main thread.  */
-      th = windows_add_thread (ptid_t (current_event.dwProcessId, 0,
-				       current_event.dwThreadId),
-	     current_event.u.CreateProcessInfo.hThread,
-	     current_event.u.CreateProcessInfo.lpThreadLocalBase);
+      th = windows_add_thread
+        (ptid_t (current_event.dwProcessId, 0,
+		 current_event.dwThreadId),
+	 current_event.u.CreateProcessInfo.hThread,
+	 current_event.u.CreateProcessInfo.lpThreadLocalBase,
+	 true /* main_thread_p */);
       thread_id = current_event.dwThreadId;
       break;
 
@@ -1601,7 +1637,7 @@  get_windows_debug_event (struct target_ops *ops,
 	{
 	  windows_delete_thread (ptid_t (current_event.dwProcessId, 0,
 					 main_thread_id),
-				 0);
+				 0, true /* main_thread_p */);
 	  ourstatus->kind = TARGET_WAITKIND_EXITED;
 	  ourstatus->value.integer = current_event.u.ExitProcess.dwExitCode;
 	  thread_id = main_thread_id;