}
}
+/* Helper for win32_process_target::kill. Resume all suspended
+ threads that match THREAD_ID, and continue the last debug event
+ with CONTINUE_STATUS. */
+
static BOOL
-child_continue (DWORD continue_status, int thread_id)
+child_continue_for_kill (DWORD continue_status, int thread_id)
{
- process_info *proc = find_process_pid (windows_process.process_id);
- for (thread_info &thread : proc->thread_list ())
- {
- auto *th = static_cast<windows_thread_info *> (thread.target_data ());
- if ((thread_id == -1 || thread_id == (int) th->tid)
- && !th->suspended
- && th->pending_stop.status.kind () != TARGET_WAITKIND_IGNORE)
- return TRUE;
- }
-
/* The inferior will only continue after the ContinueDebugEvent
call. */
for_each_thread ([&] (thread_info *thread)
TerminateProcess (windows_process.handle, 0);
for (;;)
{
- if (!child_continue (DBG_CONTINUE, -1))
+ if (!child_continue_for_kill (DBG_CONTINUE, -1))
break;
if (!wait_for_debug_event (&windows_process.current_event, INFINITE))
break;
return find_thread_ptid (ptid) != NULL;
}
-/* Resume the inferior process. RESUME_INFO describes how we want
- to resume. */
-void
-win32_process_target::resume (thread_resume *resume_info, size_t n)
-{
- DWORD tid;
- enum gdb_signal sig;
- int step;
- windows_thread_info *th;
- DWORD continue_status = DBG_CONTINUE;
- ptid_t ptid;
-
- /* This handles the very limited set of resume packets that GDB can
- currently produce. */
-
- if (n == 1 && resume_info[0].thread == minus_one_ptid)
- tid = -1;
- else if (n > 1)
- tid = -1;
- else
- /* Yes, we're ignoring resume_info[0].thread. It'd be tricky to make
- the Windows resume code do the right thing for thread switching. */
- tid = windows_process.current_event.dwThreadId;
+/* Helper for win32_process_target::resume. Resume THREAD, with
+ signal SIG, and stepping if STEP. If resuming the thread that last
+ reported an event, sets CONTINUE_STATUS appropriately to the status
+ that should be passed to ContinueDebugEvent. */
- if (resume_info[0].thread != minus_one_ptid)
- {
- sig = gdb_signal_from_host (resume_info[0].sig);
- step = resume_info[0].kind == resume_step;
- }
- else
- {
- sig = GDB_SIGNAL_0;
- step = 0;
- }
+static void
+resume_one_thread (thread_info *thread, bool step, gdb_signal sig,
+ DWORD *continue_status)
+{
+ auto *th = static_cast<windows_thread_info *> (thread->target_data ());
if (sig != GDB_SIGNAL_0)
{
- if (windows_process.current_event.dwDebugEventCode
- != EXCEPTION_DEBUG_EVENT)
+ /* Allow continuing with the same signal that interrupted us.
+ Otherwise complain. */
+ if (thread->id != get_last_debug_event_ptid ())
+ {
+ /* ContinueDebugEvent will be for a different thread. */
+ OUTMSG (("Cannot continue with signal %d here. "
+ "Not last-event thread", sig));
+ }
+ else if (windows_process.current_event.dwDebugEventCode
+ != EXCEPTION_DEBUG_EVENT)
{
- OUTMSG (("Cannot continue with signal %s here.\n",
+ OUTMSG (("Cannot continue with signal %s here. "
+ "Not stopped for EXCEPTION_DEBUG_EVENT.\n",
gdb_signal_to_string (sig)));
}
else if (sig == windows_process.last_sig)
- continue_status = DBG_EXCEPTION_NOT_HANDLED;
+ *continue_status = DBG_EXCEPTION_NOT_HANDLED;
else
OUTMSG (("Can only continue with received signal %s.\n",
gdb_signal_to_string (windows_process.last_sig)));
}
- windows_process.last_sig = GDB_SIGNAL_0;
+ win32_prepare_to_resume (th);
- /* Get context for the currently selected thread. */
- ptid = debug_event_ptid (&windows_process.current_event);
- th = windows_process.find_thread (ptid);
- if (th)
+ DWORD *context_flags = windows_process.context_flags_ptr (th);
+ if (*context_flags)
{
- win32_prepare_to_resume (th);
+ /* Move register values from the inferior into the thread
+ context structure. */
+ regcache_invalidate ();
- DWORD *context_flags = windows_process.context_flags_ptr (th);
- if (*context_flags)
+ if (step)
{
- /* Move register values from the inferior into the thread
- context structure. */
- regcache_invalidate ();
+ if (the_low_target.single_step != NULL)
+ (*the_low_target.single_step) (th);
+ else
+ error ("Single stepping is not supported "
+ "in this configuration.\n");
+ }
+
+ win32_set_thread_context (th);
+ *context_flags = 0;
+ }
+
+ continue_one_thread (thread, th->tid);
+}
+
+/* Resume the inferior process. RESUME_INFO describes how we want
+ to resume. */
+void
+win32_process_target::resume (thread_resume *resume_info, size_t n)
+{
+ DWORD continue_status = DBG_CONTINUE;
+ bool any_pending = false;
+
+ for_each_thread ([&] (thread_info *thread)
+ {
+ auto *th = static_cast<windows_thread_info *> (thread->target_data ());
- if (step)
+ for (int ndx = 0; ndx < n; ndx++)
+ {
+ thread_resume &r = resume_info[ndx];
+ ptid_t ptid = r.thread;
+ gdb_signal sig = gdb_signal_from_host (r.sig);
+ bool step = r.kind == resume_step;
+
+ if (ptid == minus_one_ptid || ptid == thread->id
+ /* Handle both 'pPID' and 'pPID.-1' as meaning 'all threads
+ of PID'. */
+ || (ptid.pid () == thread->id.pid ()
+ && (ptid.is_pid () || ptid.lwp () == -1)))
{
- if (the_low_target.single_step != NULL)
- (*the_low_target.single_step) (th);
- else
- error ("Single stepping is not supported "
- "in this configuration.\n");
- }
+ /* Ignore (wildcard) resume requests for already-resumed
+ threads. */
+ if (!th->suspended)
+ continue;
- win32_set_thread_context (th);
- *context_flags = 0;
+ resume_one_thread (thread, step, sig, &continue_status);
+ break;
+ }
}
- }
- /* Allow continuing with the same signal that interrupted us.
- Otherwise complain. */
+ if (!th->suspended
+ && th->pending_stop.status.kind () != TARGET_WAITKIND_IGNORE)
+ any_pending = true;
+ });
- child_continue (continue_status, tid);
+ if (!any_pending)
+ continue_last_debug_event (continue_status, debug_threads);
}
/* See nat/windows-nat.h. */