[25/28] Don't write to inferior_ptid in windows-nat.c, part II

Message ID 20200414175434.8047-26-palves@redhat.com
State New
Headers show
Series
  • Decouple inferior_ptid/inferior_thread(); dup ptids in thread list (PR/25412)
Related show

Commit Message

Simon Marchi via Gdb-patches April 14, 2020, 5:54 p.m.
Writing to inferior_ptid in
windows_nat_target::get_windows_debug_event is just incorrect and not
necessary.  We'll report the event to GDB's core, which then takes
care of switching inferior_ptid / current thread.

Related (see windows_nat_target::get_windows_debug_event), there's
also a "current_windows_thread" global that is just begging to get out
of sync with core GDB's current thread.  This patch removes it.
gdbserver already does not have an equivalent global in win32-low.cc.

gdb/ChangeLog:
yyyy-mm-dd  Pedro Alves  <palves@redhat.com>

	* nat/windows-nat.c (current_windows_thread): Remove.
	* nat/windows-nat.h (current_windows_thread): Remove.
	* windows-nat.c (windows_nat_target::stopped_by_sw_breakpoint):
	Adjust.
	(display_selectors): Adjust to fetch the current
	windows_thread_info based on inferior_ptid.
	(fake_create_process): No longer write to current_windows_thread.
	(windows_nat_target::get_windows_debug_event):
	Don't set inferior_ptid or current_windows_thread.
	(windows_nat_target::wait): Adjust to not rely on
	current_windows_thread.
	(windows_nat_target::detach): Use switch_to_no_thread instead of
	writing to inferior_ptid directly.
---
 gdb/nat/windows-nat.c |  1 -
 gdb/nat/windows-nat.h |  3 ---
 gdb/windows-nat.c     | 62 ++++++++++++++++++++++++++-------------------------
 3 files changed, 32 insertions(+), 34 deletions(-)

-- 
2.14.5

Comments

Simon Marchi via Gdb-patches April 14, 2020, 10:41 p.m. | #1
I did my tests now, thanks for your git branch.

Am Dienstag, 14. April 2020, 19:55:30 MESZ hat Pedro Alves via Gdb-patches <gdb-patches@sourceware.org> Folgendes geschrieben:

> Writing to inferior_ptid in

> windows_nat_target::get_windows_debug_event is just incorrect and not

> necessary.  We'll report the event to GDB's core, which then takes

> care of switching inferior_ptid / current thread.

>

> Related (see windows_nat_target::get_windows_debug_event), there's

> also a "current_windows_thread" global that is just begging to get out

> of sync with core GDB's current thread.  This patch removes it.

> gdbserver already does not have an equivalent global in win32-low.cc.

>

> gdb/ChangeLog:

> yyyy-mm-dd  Pedro Alves  <palves@redhat.com>

>

>     * nat/windows-nat.c (current_windows_thread): Remove.

>     * nat/windows-nat.h (current_windows_thread): Remove.

>     * windows-nat.c (windows_nat_target::stopped_by_sw_breakpoint):

>     Adjust.

>     (display_selectors): Adjust to fetch the current

>     windows_thread_info based on inferior_ptid.

>     (fake_create_process): No longer write to current_windows_thread.

>     (windows_nat_target::get_windows_debug_event):

>     Don't set inferior_ptid or current_windows_thread.

>     (windows_nat_target::wait): Adjust to not rely on

>     current_windows_thread.

>     (windows_nat_target::detach): Use switch_to_no_thread instead of

>     writing to inferior_ptid directly.

> ---

> gdb/nat/windows-nat.c |  1 -

> gdb/nat/windows-nat.h |  3 ---

> gdb/windows-nat.c    | 62 ++++++++++++++++++++++++++-------------------------

> 3 files changed, 32 insertions(+), 34 deletions(-)

>

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

> index cd7c1d177c..a382b9edb9 100644

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

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

> @@ -36,7 +36,6 @@ DEBUG_EVENT current_event;

>     ContinueDebugEvent.  */

> static DEBUG_EVENT last_wait_event;

>

> -windows_thread_info *current_windows_thread;

> DWORD desired_stop_thread_id = -1;

> std::vector<pending_stop> pending_stops;

> EXCEPTION_RECORD siginfo_er;

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

> index aea1519672..dc27827d9c 100644

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

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

> @@ -168,9 +168,6 @@ extern enum gdb_signal last_sig;

>     stop.  */

> extern DEBUG_EVENT current_event;

>

> -/* Info on currently selected thread */

> -extern windows_thread_info *current_windows_thread;

> -

> /* The ID of the thread for which we anticipate a stop event.

>     Normally this is -1, meaning we'll accept an event in any

>     thread.  */

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

> index 1bbebf00b9..78e7e31c67 100644

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

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

> @@ -317,7 +317,9 @@ struct windows_nat_target final : public x86_nat_target<inf_child_target>

>

>   bool stopped_by_sw_breakpoint () override

>   {

> -    return current_windows_thread->stopped_at_software_breakpoint;

> +    windows_thread_info *th

> +      = thread_rec (inferior_ptid, DONT_INVALIDATE_CONTEXT);

> +    return th->stopped_at_software_breakpoint;

>   }

>

>   bool supports_stopped_by_sw_breakpoint () override

> @@ -1125,11 +1127,15 @@ display_selector (HANDLE thread, DWORD sel)

> static void

> display_selectors (const char * args, int from_tty)

> {

> -  if (!current_windows_thread)

> +  if (inferior_ptid == null_ptid)

>     {

>       puts_filtered ("Impossible to display selectors now.\n");

>       return;

>     }

> +

> +  windows_thread_info *current_windows_thread

> +    = thread_rec (inferior_ptid, DONT_INVALIDATE_CONTEXT);

> +

>   if (!args)

>     {

> #ifdef __x86_64__

> @@ -1338,12 +1344,11 @@ fake_create_process (void)

>         (unsigned) GetLastError ());

>       /*  We can not debug anything in that case.  */

>     }

> -  current_windows_thread

> -    = windows_add_thread (ptid_t (current_event.dwProcessId,

> -                  current_event.dwThreadId, 0),

> -              current_event.u.CreateThread.hThread,

> -              current_event.u.CreateThread.lpThreadLocalBase,

> -              true /* main_thread_p */);

> +  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 current_event.dwThreadId;

> }

>

> @@ -1516,10 +1521,9 @@ windows_nat_target::get_windows_debug_event (int pid,

>       thread_id = stop->thread_id;

>       *ourstatus = stop->status;

>

> -      inferior_ptid = ptid_t (current_event.dwProcessId, thread_id, 0);

> -      current_windows_thread = thread_rec (inferior_ptid,

> -                      INVALIDATE_CONTEXT);

> -      current_windows_thread->reload_context = 1;

> +      ptid_t ptid (current_event.dwProcessId, thread_id);

> +      th = thread_rec (ptid, INVALIDATE_CONTEXT);

> +      th->reload_context = 1;

>

>       return thread_id;

>     }

> @@ -1734,14 +1738,6 @@ windows_nat_target::get_windows_debug_event (int pid,

>       thread_id = 0;

>       CHECK (windows_continue (continue_status, desired_stop_thread_id, 0));

>     }

> -  else

> -    {

> -      inferior_ptid = ptid_t (current_event.dwProcessId, thread_id, 0);

> -      current_windows_thread = th;

> -      if (!current_windows_thread)

> -    current_windows_thread = thread_rec (inferior_ptid,

> -                        INVALIDATE_CONTEXT);

> -    }

>

> out:

>   return thread_id;


The removal of these lines breaks debugging on Windows, right on startup I get:

(gdb) r
Starting program: C:\qiewer\heob\heob64.exe
C:/src/repos/binutils-gdb.git/gdb/thread.c:86: internal-error: thread_info* inferior_thread(): Assertion `tp' failed.

Full stacktrace of the assertion failure:

(gdb) bt
#0  internal_error (file=0xa713a8 <selftests::test_target_info+168> "C:/src/repos/binutils-gdb.git/gdb/thread.c", line=86,
    fmt=0xa71388 <selftests::test_target_info+136> "%s: Assertion `%s' failed.") at C:/src/repos/binutils-gdb.git/gdbsupport/errors.cc:51
#1  0x000000000066cfd9 in inferior_thread () at C:/src/repos/binutils-gdb.git/gdb/thread.c:86
#2  inferior_thread () at C:/src/repos/binutils-gdb.git/gdb/thread.c:83
#3  0x00000000005603a0 in post_create_inferior (target=0x999ba0 <the_windows_nat_target>, from_tty=from_tty@entry=0)
    at C:/src/repos/binutils-gdb.git/gdb/infcmd.c:444
#4  0x0000000000563727 in run_command_1 (args=<optimized out>, from_tty=1, run_how=RUN_NORMAL) at C:/src/repos/binutils-gdb.git/gdb/infcmd.c:670
#5  0x00000000004810c2 in cmd_func (cmd=0xa713a8 <selftests::test_target_info+168>, args=0x56 <error: Cannot access memory at address 0x56>,
    from_tty=10949512) at C:/src/repos/binutils-gdb.git/gdb/cli/cli-decode.c:1952
#6  0x00000000006735a8 in execute_command (p=<optimized out>, p@entry=0x13bae0 "", from_tty=1) at C:/src/repos/binutils-gdb.git/gdb/top.c:655
#7  0x00000000005153f4 in command_handler (command=0x13bae0 "") at C:/src/repos/binutils-gdb.git/gdb/event-top.c:588
#8  0x00000000005162a2 in command_line_handler (rl=...) at C:/src/repos/binutils-gdb.git/gdb/event-top.c:773
#9  0x0000000000515bd3 in gdb_rl_callback_handler (rl=0x13b4c0 "r") at c:/msys64/mingw64/x86_64-w64-mingw32/include/c++/9.3.0/bits/unique_ptr.h:153
#10 0x00000000006e4eec in rl_callback_read_char () at C:/src/repos/binutils-gdb.git/readline/readline/callback.c:281
#11 0x0000000000514f4e in gdb_rl_callback_read_char_wrapper_noexcept () at C:/src/repos/binutils-gdb.git/gdb/event-top.c:177
#12 0x0000000000515a84 in gdb_rl_callback_read_char_wrapper (client_data=<optimized out>) at C:/src/repos/binutils-gdb.git/gdb/event-top.c:193
#13 0x0000000000514d92 in stdin_event_handler (error=<optimized out>, client_data=0x13b720) at C:/src/repos/binutils-gdb.git/gdb/event-top.c:516
#14 0x00000000007a91e0 in handle_file_event (ready_mask=2, file_ptr=0x1e93c0) at C:/src/repos/binutils-gdb.git/gdbsupport/event-loop.cc:548
#15 gdb_wait_for_event (block=<optimized out>) at C:/src/repos/binutils-gdb.git/gdbsupport/event-loop.cc:698
#16 gdb_wait_for_event (block=<optimized out>) at C:/src/repos/binutils-gdb.git/gdbsupport/event-loop.cc:561
#17 0x00000000007a9318 in gdb_do_one_event () at C:/src/repos/binutils-gdb.git/gdbsupport/event-loop.cc:215
#18 0x0000000000592c4d in start_event_loop () at C:/src/repos/binutils-gdb.git/gdb/main.c:356
#19 captured_command_loop () at C:/src/repos/binutils-gdb.git/gdb/main.c:416
#20 0x0000000000594b55 in captured_main (data=0xfd4fdc0) at C:/src/repos/binutils-gdb.git/gdb/main.c:1254
#21 gdb_main (args=args@entry=0xfd4fe20) at C:/src/repos/binutils-gdb.git/gdb/main.c:1269
#22 0x000000000098a757 in main (argc=3, argv=0x1048a0) at C:/src/repos/binutils-gdb.git/gdb/gdb.c:32
(gdb) up
#1  0x000000000066cfd9 in inferior_thread () at C:/src/repos/binutils-gdb.git/gdb/thread.c:86
86        gdb_assert (tp);
(gdb) l
81
82      struct thread_info*
83      inferior_thread (void)
84      {
85        struct thread_info *tp = find_thread_ptid (current_inferior (), inferior_ptid);
86        gdb_assert (tp);
87        return tp;
88      }
89
90      /* Delete the breakpoint pointed at by BP_P, if there's one.  */


This replacement works fine for me so far:

diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c
index 78e7e31c67..b22df182a1 100644
--- a/gdb/windows-nat.c
+++ b/gdb/windows-nat.c
@@ -1738,6 +1738,12 @@ windows_nat_target::get_windows_debug_event (int pid,
       thread_id = 0;
       CHECK (windows_continue (continue_status, desired_stop_thread_id, 0));
     }
+  else
+    {
+      if (th != nullptr)
+       switch_to_thread (&the_windows_nat_target,
+                         ptid_t (current_event.dwProcessId, thread_id, 0));
+    }

 out:
   return thread_id;


Btw., I think this variable in get_windows_debug_event is no longer useful:
  static windows_thread_info dummy_thread_info (0, 0, 0);


Hannes
Simon Marchi via Gdb-patches April 15, 2020, 3:08 p.m. | #2
On 4/14/20 11:41 PM, Hannes Domani via Gdb-patches wrote:

> The removal of these lines breaks debugging on Windows, right on startup I get:

> 

> (gdb) r

> Starting program: C:\qiewer\heob\heob64.exe

> C:/src/repos/binutils-gdb.git/gdb/thread.c:86: internal-error: thread_info* inferior_thread(): Assertion `tp' failed.

> 

> Full stacktrace of the assertion failure:

> 

> (gdb) bt

> #0  internal_error (file=0xa713a8 <selftests::test_target_info+168> "C:/src/repos/binutils-gdb.git/gdb/thread.c", line=86,

>     fmt=0xa71388 <selftests::test_target_info+136> "%s: Assertion `%s' failed.") at C:/src/repos/binutils-gdb.git/gdbsupport/errors.cc:51

> #1  0x000000000066cfd9 in inferior_thread () at C:/src/repos/binutils-gdb.git/gdb/thread.c:86

> #2  inferior_thread () at C:/src/repos/binutils-gdb.git/gdb/thread.c:83

> #3  0x00000000005603a0 in post_create_inferior (target=0x999ba0 <the_windows_nat_target>, from_tty=from_tty@entry=0)

>     at C:/src/repos/binutils-gdb.git/gdb/infcmd.c:444

> #4  0x0000000000563727 in run_command_1 (args=<optimized out>, from_tty=1, run_how=RUN_NORMAL) at C:/src/repos/binutils-gdb.git/gdb/infcmd.c:670


> Btw., I think this variable in get_windows_debug_event is no longer useful:

>   static windows_thread_info dummy_thread_info (0, 0, 0);

> 


Thanks for pointing that out.

> 

> This replacement works fine for me so far:


Does this instead work for you?  This adds a single
switch_to_thread at the end of the initialization.

From 00648f5a0bd7b8d85a2bdf49a2d8f71087826062 Mon Sep 17 00:00:00 2001
From: Pedro Alves <palves@redhat.com>

Date: Wed, 15 Apr 2020 15:52:32 +0100
Subject: [PATCH] Fix Windows

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

diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c
index 78e7e31c67..dd15fa1fab 100644
--- a/gdb/windows-nat.c
+++ b/gdb/windows-nat.c
@@ -358,6 +358,8 @@ struct windows_nat_target final : public x86_nat_target<inf_child_target>
   const char *thread_name (struct thread_info *) override;
 
   int get_windows_debug_event (int pid, struct target_waitstatus *ourstatus);
+
+  void do_initial_windows_stuff (DWORD pid, bool attaching);
 };
 
 static windows_nat_target the_windows_nat_target;
@@ -1508,8 +1510,6 @@ windows_nat_target::get_windows_debug_event (int pid,
 {
   BOOL debug_event;
   DWORD continue_status, event_code;
-  windows_thread_info *th;
-  static windows_thread_info dummy_thread_info (0, 0, 0);
   DWORD thread_id = 0;
 
   /* If there is a relevant pending stop, report it now.  See the
@@ -1522,7 +1522,7 @@ windows_nat_target::get_windows_debug_event (int pid,
       *ourstatus = stop->status;
 
       ptid_t ptid (current_event.dwProcessId, thread_id);
-      th = thread_rec (ptid, INVALIDATE_CONTEXT);
+      windows_thread_info *th = thread_rec (ptid, INVALIDATE_CONTEXT);
       th->reload_context = 1;
 
       return thread_id;
@@ -1537,7 +1537,6 @@ windows_nat_target::get_windows_debug_event (int pid,
 
   event_code = current_event.dwDebugEventCode;
   ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
-  th = NULL;
   have_saved_context = 0;
 
   switch (event_code)
@@ -1563,7 +1562,7 @@ windows_nat_target::get_windows_debug_event (int pid,
 	}
       /* Record the existence of this thread.  */
       thread_id = current_event.dwThreadId;
-      th = windows_add_thread
+      windows_add_thread
         (ptid_t (current_event.dwProcessId, current_event.dwThreadId, 0),
 	 current_event.u.CreateThread.hThread,
 	 current_event.u.CreateThread.lpThreadLocalBase,
@@ -1580,7 +1579,6 @@ windows_nat_target::get_windows_debug_event (int pid,
 				     current_event.dwThreadId, 0),
 			     current_event.u.ExitThread.dwExitCode,
 			     false /* main_thread_p */);
-      th = &dummy_thread_info;
       break;
 
     case CREATE_PROCESS_DEBUG_EVENT:
@@ -1594,7 +1592,7 @@ windows_nat_target::get_windows_debug_event (int pid,
 
       current_process_handle = current_event.u.CreateProcessInfo.hProcess;
       /* Add the main thread.  */
-      th = windows_add_thread
+      windows_add_thread
         (ptid_t (current_event.dwProcessId,
 		 current_event.dwThreadId, 0),
 	 current_event.u.CreateProcessInfo.hThread,
@@ -1731,7 +1729,7 @@ windows_nat_target::get_windows_debug_event (int pid,
 	  && windows_initialization_done)
 	{
 	  ptid_t ptid = ptid_t (current_event.dwProcessId, thread_id, 0);
-	  th = thread_rec (ptid, INVALIDATE_CONTEXT);
+	  windows_thread_info *th = thread_rec (ptid, INVALIDATE_CONTEXT);
 	  th->stopped_at_software_breakpoint = true;
 	}
       pending_stops.push_back ({thread_id, *ourstatus, current_event});
@@ -1944,8 +1942,8 @@ windows_add_all_dlls (void)
     }
 }
 
-static void
-do_initial_windows_stuff (struct target_ops *ops, DWORD pid, int attaching)
+void
+windows_nat_target::do_initial_windows_stuff (DWORD pid, bool attaching)
 {
   int i;
   struct inferior *inf;
@@ -1961,8 +1959,8 @@ do_initial_windows_stuff (struct target_ops *ops, DWORD pid, int attaching)
 #endif
   current_event.dwProcessId = pid;
   memset (&current_event, 0, sizeof (current_event));
-  if (!target_is_pushed (ops))
-    push_target (ops);
+  if (!target_is_pushed (this))
+    push_target (this);
   disable_breakpoints_in_shlibs ();
   windows_clear_solib ();
   clear_proceed_status (0);
@@ -1992,11 +1990,13 @@ do_initial_windows_stuff (struct target_ops *ops, DWORD pid, int attaching)
 
   windows_initialization_done = 0;
 
+  ptid_t last_ptid;
+
   while (1)
     {
       struct target_waitstatus status;
 
-      ops->wait (minus_one_ptid, &status, 0);
+      last_ptid = this->wait (minus_one_ptid, &status, 0);
 
       /* Note windows_wait returns TARGET_WAITKIND_SPURIOUS for thread
 	 events.  */
@@ -2004,9 +2004,11 @@ do_initial_windows_stuff (struct target_ops *ops, DWORD pid, int attaching)
 	  && status.kind != TARGET_WAITKIND_SPURIOUS)
 	break;
 
-      ops->resume (minus_one_ptid, 0, GDB_SIGNAL_0);
+      this->resume (minus_one_ptid, 0, GDB_SIGNAL_0);
     }
 
+  switch_to_thread (find_thread_ptid (this, last_ptid));
+
   /* Now that the inferior has been started and all DLLs have been mapped,
      we can iterate over all DLLs and load them in.
 
@@ -2138,7 +2140,7 @@ windows_nat_target::attach (const char *args, int from_tty)
     }
 #endif
 
-  do_initial_windows_stuff (this, pid, 1);
+  do_initial_windows_stuff (pid, 1);
   target_terminal::ours ();
 }
 
@@ -2978,9 +2980,8 @@ windows_nat_target::create_inferior (const char *exec_file,
   else
     saw_create = 0;
 
-  do_initial_windows_stuff (this, pi.dwProcessId, 0);
+  do_initial_windows_stuff (pi.dwProcessId, 0);
 
   /* windows_continue (DBG_CONTINUE, -1, 0); */
 }

-- 
2.14.5
Simon Marchi via Gdb-patches April 15, 2020, 3:32 p.m. | #3
Am Mittwoch, 15. April 2020, 17:08:27 MESZ hat Pedro Alves <palves@redhat.com> Folgendes geschrieben:

> On 4/14/20 11:41 PM, Hannes Domani via Gdb-patches wrote:

>

> > The removal of these lines breaks debugging on Windows, right on startup I get:

> >

> > (gdb) r

> > Starting program: C:\qiewer\heob\heob64.exe

> > C:/src/repos/binutils-gdb.git/gdb/thread.c:86: internal-error: thread_info* inferior_thread(): Assertion `tp' failed.

> >

> > Full stacktrace of the assertion failure:

> >

> > (gdb) bt

> > #0  internal_error (file=0xa713a8 <selftests::test_target_info+168> "C:/src/repos/binutils-gdb.git/gdb/thread.c", line=86,

> >     fmt=0xa71388 <selftests::test_target_info+136> "%s: Assertion `%s' failed.") at C:/src/repos/binutils-gdb.git/gdbsupport/errors.cc:51

> > #1  0x000000000066cfd9 in inferior_thread () at C:/src/repos/binutils-gdb.git/gdb/thread.c:86

> > #2  inferior_thread () at C:/src/repos/binutils-gdb.git/gdb/thread.c:83

> > #3  0x00000000005603a0 in post_create_inferior (target=0x999ba0 <the_windows_nat_target>, from_tty=from_tty@entry=0)

> >     at C:/src/repos/binutils-gdb.git/gdb/infcmd.c:444

> > #4  0x0000000000563727 in run_command_1 (args=<optimized out>, from_tty=1, run_how=RUN_NORMAL) at C:/src/repos/binutils-gdb.git/gdb/infcmd.c:670

>

> > Btw., I think this variable in get_windows_debug_event is no longer useful:

> >  static windows_thread_info dummy_thread_info (0, 0, 0);

> >

>

> Thanks for pointing that out.

>

> >

> > This replacement works fine for me so far:

>

> Does this instead work for you?  This adds a single

> switch_to_thread at the end of the initialization.


Yes, this also works for me.


Hannes

Patch

diff --git a/gdb/nat/windows-nat.c b/gdb/nat/windows-nat.c
index cd7c1d177c..a382b9edb9 100644
--- a/gdb/nat/windows-nat.c
+++ b/gdb/nat/windows-nat.c
@@ -36,7 +36,6 @@  DEBUG_EVENT current_event;
    ContinueDebugEvent.  */
 static DEBUG_EVENT last_wait_event;
 
-windows_thread_info *current_windows_thread;
 DWORD desired_stop_thread_id = -1;
 std::vector<pending_stop> pending_stops;
 EXCEPTION_RECORD siginfo_er;
diff --git a/gdb/nat/windows-nat.h b/gdb/nat/windows-nat.h
index aea1519672..dc27827d9c 100644
--- a/gdb/nat/windows-nat.h
+++ b/gdb/nat/windows-nat.h
@@ -168,9 +168,6 @@  extern enum gdb_signal last_sig;
    stop.  */
 extern DEBUG_EVENT current_event;
 
-/* Info on currently selected thread */
-extern windows_thread_info *current_windows_thread;
-
 /* The ID of the thread for which we anticipate a stop event.
    Normally this is -1, meaning we'll accept an event in any
    thread.  */
diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c
index 1bbebf00b9..78e7e31c67 100644
--- a/gdb/windows-nat.c
+++ b/gdb/windows-nat.c
@@ -317,7 +317,9 @@  struct windows_nat_target final : public x86_nat_target<inf_child_target>
 
   bool stopped_by_sw_breakpoint () override
   {
-    return current_windows_thread->stopped_at_software_breakpoint;
+    windows_thread_info *th
+      = thread_rec (inferior_ptid, DONT_INVALIDATE_CONTEXT);
+    return th->stopped_at_software_breakpoint;
   }
 
   bool supports_stopped_by_sw_breakpoint () override
@@ -1125,11 +1127,15 @@  display_selector (HANDLE thread, DWORD sel)
 static void
 display_selectors (const char * args, int from_tty)
 {
-  if (!current_windows_thread)
+  if (inferior_ptid == null_ptid)
     {
       puts_filtered ("Impossible to display selectors now.\n");
       return;
     }
+
+  windows_thread_info *current_windows_thread
+    = thread_rec (inferior_ptid, DONT_INVALIDATE_CONTEXT);
+
   if (!args)
     {
 #ifdef __x86_64__
@@ -1338,12 +1344,11 @@  fake_create_process (void)
        (unsigned) GetLastError ());
       /*  We can not debug anything in that case.  */
     }
-  current_windows_thread
-    = windows_add_thread (ptid_t (current_event.dwProcessId,
-				  current_event.dwThreadId, 0),
-			  current_event.u.CreateThread.hThread,
-			  current_event.u.CreateThread.lpThreadLocalBase,
-			  true /* main_thread_p */);
+  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 current_event.dwThreadId;
 }
 
@@ -1516,10 +1521,9 @@  windows_nat_target::get_windows_debug_event (int pid,
       thread_id = stop->thread_id;
       *ourstatus = stop->status;
 
-      inferior_ptid = ptid_t (current_event.dwProcessId, thread_id, 0);
-      current_windows_thread = thread_rec (inferior_ptid,
-					   INVALIDATE_CONTEXT);
-      current_windows_thread->reload_context = 1;
+      ptid_t ptid (current_event.dwProcessId, thread_id);
+      th = thread_rec (ptid, INVALIDATE_CONTEXT);
+      th->reload_context = 1;
 
       return thread_id;
     }
@@ -1734,14 +1738,6 @@  windows_nat_target::get_windows_debug_event (int pid,
       thread_id = 0;
       CHECK (windows_continue (continue_status, desired_stop_thread_id, 0));
     }
-  else
-    {
-      inferior_ptid = ptid_t (current_event.dwProcessId, thread_id, 0);
-      current_windows_thread = th;
-      if (!current_windows_thread)
-	current_windows_thread = thread_rec (inferior_ptid,
-					     INVALIDATE_CONTEXT);
-    }
 
 out:
   return thread_id;
@@ -1798,16 +1794,22 @@  windows_nat_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus,
 	{
 	  ptid_t result = ptid_t (current_event.dwProcessId, retval, 0);
 
-	  if (current_windows_thread != nullptr)
+	  if (ourstatus->kind != TARGET_WAITKIND_EXITED
+	      && ourstatus->kind !=  TARGET_WAITKIND_SIGNALLED)
 	    {
-	      current_windows_thread->stopped_at_software_breakpoint = false;
-	      if (current_event.dwDebugEventCode == EXCEPTION_DEBUG_EVENT
-		  && ((current_event.u.Exception.ExceptionRecord.ExceptionCode
-		       == EXCEPTION_BREAKPOINT)
-		      || (current_event.u.Exception.ExceptionRecord.ExceptionCode
-			  == STATUS_WX86_BREAKPOINT))
-		  && windows_initialization_done)
-		current_windows_thread->stopped_at_software_breakpoint = true;
+	      windows_thread_info *th = thread_rec (result, INVALIDATE_CONTEXT);
+
+	      if (th != nullptr)
+		{
+		  th->stopped_at_software_breakpoint = false;
+		  if (current_event.dwDebugEventCode == EXCEPTION_DEBUG_EVENT
+		      && ((current_event.u.Exception.ExceptionRecord.ExceptionCode
+			   == EXCEPTION_BREAKPOINT)
+			  || (current_event.u.Exception.ExceptionRecord.ExceptionCode
+			      == STATUS_WX86_BREAKPOINT))
+		      && windows_initialization_done)
+		    th->stopped_at_software_breakpoint = true;
+		}
 	    }
 
 	  return result;
@@ -2166,7 +2168,7 @@  windows_nat_target::detach (inferior *inf, int from_tty)
     }
 
   x86_cleanup_dregs ();
-  inferior_ptid = null_ptid;
+  switch_to_no_thread ();
   detach_inferior (inf);
 
   maybe_unpush_target ();