From: Pedro Alves <pedro@codesourcery.com>
To: "Pierre Muller" <muller@ics.u-strasbg.fr>
Cc: "'Joel Brobecker'" <brobecker@adacore.com>, gdb-patches@sourceware.org
Subject: Re: [BUG] Quit and "(running)" problem
Date: Thu, 15 Jan 2009 22:15:00 -0000 [thread overview]
Message-ID: <200901152215.00564.pedro@codesourcery.com> (raw)
In-Reply-To: <000001c9772a$a1fb69f0$e5f23dd0$@u-strasbg.fr>
[-- Attachment #1: Type: text/plain, Size: 106 bytes --]
Something like this should handle your case and similars. Could you try it out, please?
--
Pedro Alves
[-- Attachment #2: pr9747.diff --]
[-- Type: text/x-diff, Size: 9202 bytes --]
2009-01-15 Pedro Alves <pedro@codesourcery.com>
PR gdb/9747:
* gdbthread.h (finish_thread_state, finish_thread_state_cleanup):
Declare.
* thread.c (finish_thread_state, finish_thread_state_cleanup): New.
* infrun.c (wait_for_inferior, fetch_inferior_event): If an error
is thrown while handling an event, finish the thread state.
* infcmd.c (run_command_1): If an error is thrown while starting
the inferior, finish the thread state.
---
gdb/gdbthread.h | 17 +++++++++++++++++
gdb/infcmd.c | 19 ++++++++++++++++++-
gdb/infrun.c | 51 +++++++++++++++++++++++++++++++++++++++------------
gdb/thread.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 123 insertions(+), 13 deletions(-)
Index: src/gdb/gdbthread.h
===================================================================
--- src.orig/gdb/gdbthread.h 2009-01-15 21:37:10.000000000 +0000
+++ src/gdb/gdbthread.h 2009-01-15 21:38:06.000000000 +0000
@@ -288,6 +288,23 @@ extern void set_executing (ptid_t ptid,
/* Reports if thread PTID is executing. */
extern int is_executing (ptid_t ptid);
+/* Merge the executing property of thread PTID over to its thread
+ state property (frontend running/stopped view).
+
+ "not executing" -> "stopped"
+ "executing" -> "running"
+ "exited" -> "exited"
+
+ If PIDGET (PTID) is -1, go over all threads.
+
+ Notifications are only emitted if the thread state did change. */
+extern void finish_thread_state (ptid_t ptid);
+
+/* Same as FINISH_THREAD_STATE, but with an interface suitable to be
+ registered as a cleanup. PTID_P points to the ptid_t that is
+ passed to FINISH_THREAD_STATE. */
+extern void finish_thread_state_cleanup (void *ptid_p);
+
/* Commands with a prefix of `thread'. */
extern struct cmd_list_element *thread_cmd_list;
Index: src/gdb/thread.c
===================================================================
--- src.orig/gdb/thread.c 2009-01-15 21:37:10.000000000 +0000
+++ src/gdb/thread.c 2009-01-15 21:37:11.000000000 +0000
@@ -632,6 +632,55 @@ set_stop_requested (ptid_t ptid, int sto
observer_notify_thread_stop_requested (ptid);
}
+void
+finish_thread_state (ptid_t ptid)
+{
+ struct thread_info *tp;
+ int all;
+ int any_started = 0;
+
+ all = ptid_equal (ptid, minus_one_ptid);
+
+ if (all || ptid_is_pid (ptid))
+ {
+ for (tp = thread_list; tp; tp = tp->next)
+ {
+ if (tp->state_ == THREAD_EXITED)
+ continue;
+ if (all || ptid_get_pid (ptid) == ptid_get_pid (tp->ptid))
+ {
+ if (tp->executing_ && tp->state_ == THREAD_STOPPED)
+ any_started = 1;
+ tp->state_ = tp->executing_ ? THREAD_RUNNING : THREAD_STOPPED;
+ }
+ }
+ }
+ else
+ {
+ tp = find_thread_pid (ptid);
+ gdb_assert (tp);
+ if (tp->state_ != THREAD_EXITED)
+ {
+ if (tp->executing_ && tp->state_ == THREAD_STOPPED)
+ any_started = 1;
+ tp->state_ = tp->executing_ ? THREAD_RUNNING : THREAD_STOPPED;
+ }
+ }
+
+ if (any_started)
+ observer_notify_target_resumed (ptid);
+}
+
+void
+finish_thread_state_cleanup (void *arg)
+{
+ ptid_t *ptid_p = arg;
+
+ gdb_assert (arg);
+
+ finish_thread_state (*ptid_p);
+}
+
/* Prints the list of threads and their details on UIOUT.
This is a version of 'info_thread_command' suitable for
use from MI.
Index: src/gdb/infrun.c
===================================================================
--- src.orig/gdb/infrun.c 2009-01-15 21:37:10.000000000 +0000
+++ src/gdb/infrun.c 2009-01-15 21:37:11.000000000 +0000
@@ -1783,6 +1783,8 @@ wait_for_inferior (int treat_exec_as_sig
while (1)
{
+ struct cleanup *old_chain;
+
if (deprecated_target_wait_hook)
ecs->ptid = deprecated_target_wait_hook (waiton_ptid, &ecs->ws);
else
@@ -1795,9 +1797,17 @@ wait_for_inferior (int treat_exec_as_sig
ecs->ws.value.sig = TARGET_SIGNAL_TRAP;
}
+ /* If an error happens while handling the event, propagate GDB's
+ knowledge of the executing state to the frontend/user running
+ state. */
+ old_chain = make_cleanup (finish_thread_state_cleanup, &minus_one_ptid);
+
/* Now figure out what to do with the result of the result. */
handle_inferior_event (ecs);
+ /* No error, don't finish the state yet. */
+ discard_cleanups (old_chain);
+
if (!ecs->wait_some_more)
break;
}
@@ -1820,6 +1830,7 @@ fetch_inferior_event (void *client_data)
struct execution_control_state ecss;
struct execution_control_state *ecs = &ecss;
struct cleanup *old_chain = make_cleanup (null_cleanup, NULL);
+ struct cleanup *ts_old_chain;
int was_sync = sync_execution;
memset (ecs, 0, sizeof (*ecs));
@@ -1863,6 +1874,14 @@ fetch_inferior_event (void *client_data)
thread. */
context_switch (ecs->ptid);
+ /* If an error happens while handling the event, propagate GDB's
+ knowledge of the executing state to the frontend/user running
+ state. */
+ if (!non_stop)
+ ts_old_chain = make_cleanup (finish_thread_state_cleanup, &minus_one_ptid);
+ else
+ ts_old_chain = make_cleanup (finish_thread_state_cleanup, &ecs->ptid);
+
/* Now figure out what to do with the result of the result. */
handle_inferior_event (ecs);
@@ -1886,6 +1905,9 @@ fetch_inferior_event (void *client_data)
inferior_event_handler (INF_EXEC_COMPLETE, NULL);
}
+ /* No error, don't finish the thread states yet. */
+ discard_cleanups (ts_old_chain);
+
/* Revert thread and frame. */
do_cleanups (old_chain);
@@ -4161,9 +4183,23 @@ normal_stop (void)
{
struct target_waitstatus last;
ptid_t last_ptid;
+ struct cleanup *old_chain = make_cleanup (null_cleanup, NULL);
get_last_target_status (&last_ptid, &last);
+ /* If an exception is thrown from this point on, make sure to
+ propagate GDB's knowledge of the executing state to the
+ frontend/user running state. A QUIT is an easy exception to see
+ here, so do this before any filtered output. */
+ if (target_has_execution)
+ {
+ if (!non_stop)
+ old_chain = make_cleanup (finish_thread_state_cleanup, &minus_one_ptid);
+ else if (last.kind != TARGET_WAITKIND_SIGNALLED
+ && last.kind != TARGET_WAITKIND_EXITED)
+ old_chain = make_cleanup (finish_thread_state_cleanup, &last_ptid);
+ }
+
/* In non-stop mode, we don't want GDB to switch threads behind the
user's back, to avoid races where the user is typing a command to
apply to thread x, but GDB switches to thread y before the user
@@ -4383,20 +4419,11 @@ done:
/* Delete the breakpoint we stopped at, if it wants to be deleted.
Delete any breakpoint that is to be deleted at the next stop. */
breakpoint_auto_delete (inferior_thread ()->stop_bpstat);
-
- /* Mark the stopped threads accordingly. In all-stop, all
- threads of all processes are stopped when we get any event
- reported. In non-stop mode, only the event thread stops. If
- we're handling a process exit in non-stop mode, there's
- nothing to do, as threads of the dead process are gone, and
- threads of any other process were left running. */
- if (!non_stop)
- set_running (minus_one_ptid, 0);
- else if (last.kind != TARGET_WAITKIND_SIGNALLED
- && last.kind != TARGET_WAITKIND_EXITED)
- set_running (inferior_ptid, 0);
}
+ /* Tell the frontend about the new thread states. */
+ do_cleanups (old_chain);
+
/* Look up the hook_stop and run it (CLI internally handles problem
of stop_command's pre-hook not existing). */
if (stop_command)
Index: src/gdb/infcmd.c
===================================================================
--- src.orig/gdb/infcmd.c 2009-01-15 21:37:10.000000000 +0000
+++ src/gdb/infcmd.c 2009-01-15 21:37:11.000000000 +0000
@@ -456,6 +456,8 @@ static void
run_command_1 (char *args, int from_tty, int tbreak_at_main)
{
char *exec_file;
+ struct cleanup *old_chain;
+ ptid_t ptid;
dont_repeat ();
@@ -544,14 +546,29 @@ run_command_1 (char *args, int from_tty,
target_create_inferior (exec_file, get_inferior_args (),
environ_vector (inferior_environ), from_tty);
+ /* We're starting off a new process. When we get out of here, in
+ non-stop mode, finish the state of all threads of that process,
+ but leave other threads alone, as they may be stopped in internal
+ events --- the frontend shouldn't seem them as stopped. In
+ all-stop, always finish the state of all threads, as we may be
+ resuming more than just the new process. */
+ if (non_stop)
+ ptid = pid_to_ptid (ptid_get_pid (inferior_ptid));
+ else
+ ptid = minus_one_ptid;
+ old_chain = make_cleanup (finish_thread_state_cleanup, &ptid);
+
/* Pass zero for FROM_TTY, because at this point the "run" command
has done its thing; now we are setting up the running program. */
post_create_inferior (¤t_target, 0);
/* Start the target running. */
proceed ((CORE_ADDR) -1, TARGET_SIGNAL_0, 0);
-}
+ /* Since there was no error, there's no need to finish the thread
+ states here. */
+ discard_cleanups (old_chain);
+}
static void
run_command (char *args, int from_tty)
next prev parent reply other threads:[~2009-01-15 22:15 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-01-15 12:40 Pierre Muller
2009-01-15 13:59 ` Joel Brobecker
2009-01-15 16:03 ` Pierre Muller
2009-01-15 22:15 ` Pedro Alves [this message]
2009-01-16 8:55 ` Pierre Muller
2009-01-16 15:13 ` Pedro Alves
2009-01-16 15:39 ` Pierre Muller
2009-01-15 14:42 ` Pedro Alves
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=200901152215.00564.pedro@codesourcery.com \
--to=pedro@codesourcery.com \
--cc=brobecker@adacore.com \
--cc=gdb-patches@sourceware.org \
--cc=muller@ics.u-strasbg.fr \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox