From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 22953 invoked by alias); 6 Feb 2009 07:44:46 -0000 Received: (qmail 22942 invoked by uid 22791); 6 Feb 2009 07:44:44 -0000 X-SWARE-Spam-Status: No, hits=-2.3 required=5.0 tests=AWL,BAYES_00,SPF_PASS X-Spam-Check-By: sourceware.org Received: from mail.codesourcery.com (HELO mail.codesourcery.com) (65.74.133.4) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Fri, 06 Feb 2009 07:44:39 +0000 Received: (qmail 11271 invoked from network); 6 Feb 2009 07:44:37 -0000 Received: from unknown (HELO wind.local) (vladimir@127.0.0.2) by mail.codesourcery.com with ESMTPA; 6 Feb 2009 07:44:37 -0000 From: Vladimir Prus To: gdb-patches@sources.redhat.com, Nick Roberts , Marc Khouzam Subject: [RFA] fix *stopped for CLI commands Date: Fri, 06 Feb 2009 07:44:00 -0000 User-Agent: KMail/1.9.10 MIME-Version: 1.0 Content-Type: Multipart/Mixed; boundary="Boundary-00=_Oq+iJCqpD0Iidhc" Message-Id: <200902061045.18508.vladimir@codesourcery.com> Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2009-02/txt/msg00151.txt.bz2 --Boundary-00=_Oq+iJCqpD0Iidhc Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Content-Disposition: inline Content-length: 1225 In gdb 6.8, typing CLI commands in MI session does not produce either *running, or ^running or *stopped messages. I've checked in some patches previous to improve that, but *stopped turns out to be not finished yet -- when in non-async mode, CLI commands such as 'continue' result in *stopped, but it has no frame information. The reason is that *stopped is printed by normal_stop observer, and the frame information is printed by normal_stop function, in infrun.c. When a CLI command is executed, we switch to the CLI interpreter and CLI uiout. In async mode, the command execution is done, we switch back to MI uiout, and then we handle stop event, so infrun.c:normal_stop prints frame into MI uiout and then MI observer puts that data out. In sync mode, however, infrun.c:normal_stop is called when the uiout is still CLI uiout, and then MI observer does not have any way to access the fields printed into CLI uiout. This patch fixes this by making MI observer print frame again, into MI uiout, if necessary. It passes all MI tests in (sync,async)x(native,gdbserver) combinations. How does this look, and are non-MI changes OK? If approved, I'll add a test that CLI commands result in proper *stopped. Thanks, Volodya --Boundary-00=_Oq+iJCqpD0Iidhc Content-Type: text/x-diff; charset="iso 8859-15"; name="stopped.diff" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="stopped.diff" Content-length: 8473 commit b9adf85d3252a9ed41c76bad645ca13af4efa027 Author: Vladimir Prus Date: Fri Feb 6 10:39:17 2009 +0300 Include frame information for *stopped due to CLI commands. gdb/doc/ * observer.texi: Add parameter 'print_frame' to normal_stop observer. * ada-tasks.c (ada_normal_stop_observer): Adjust prototype. * infcmd.c (finish_command_continuation): Pass '1' for 'print_frame' parameter to the observer. * infrun.c (normal_stop): Don't print mi-specific information here. Pass 'stop_print_frame' to the 'print_frame' parameter of the observer. * mi/mi-interp.c (mi_on_normal_stop): Adjust prototype. If we need to print frame, and current uiout is not the MI one, print frame again. gdb/testsuite/ * lib/mi-support.exp (mi_expect_stop): Adjust the order of fields. (mi_expect_interrupt): Likewise. diff --git a/gdb/ada-tasks.c b/gdb/ada-tasks.c index 5176d75..3639472 100644 --- a/gdb/ada-tasks.c +++ b/gdb/ada-tasks.c @@ -951,7 +951,7 @@ ada_task_list_changed (void) /* The 'normal_stop' observer notification callback. */ static void -ada_normal_stop_observer (struct bpstats *unused_args) +ada_normal_stop_observer (struct bpstats *unused_args, int unused_args2) { /* The inferior has been resumed, and just stopped. This means that our task_list needs to be recomputed before it can be used again. */ diff --git a/gdb/doc/observer.texi b/gdb/doc/observer.texi index 636658a..8327fea 100644 --- a/gdb/doc/observer.texi +++ b/gdb/doc/observer.texi @@ -88,7 +88,7 @@ Send a notification to all @var{event} observers. The following observable events are defined: -@deftypefun void normal_stop (struct bpstats *@var{bs}) +@deftypefun void normal_stop (struct bpstats *@var{bs}, int @var{print_frame}) The inferior has stopped for real. @end deftypefun diff --git a/gdb/infcmd.c b/gdb/infcmd.c index 3696f79..188077c 100644 --- a/gdb/infcmd.c +++ b/gdb/infcmd.c @@ -1374,7 +1374,7 @@ finish_command_continuation (void *arg) next stop will be in the same thread that we started doing a finish on. This suppressing (or some other replacement means) should be a thread property. */ - observer_notify_normal_stop (bs); + observer_notify_normal_stop (bs, 1 /* print frame */); suppress_stop_observer = 0; delete_breakpoint (a->breakpoint); } diff --git a/gdb/infrun.c b/gdb/infrun.c index c11c71a..e50ef49 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -4351,22 +4351,6 @@ Further execution is probably impossible.\n")); internal_error (__FILE__, __LINE__, _("Unknown value.")); } - if (ui_out_is_mi_like_p (uiout)) - { - - ui_out_field_int (uiout, "thread-id", - pid_to_thread_id (inferior_ptid)); - if (non_stop) - { - struct cleanup *back_to = make_cleanup_ui_out_list_begin_end - (uiout, "stopped-threads"); - ui_out_field_int (uiout, NULL, - pid_to_thread_id (inferior_ptid)); - do_cleanups (back_to); - } - else - ui_out_field_string (uiout, "stopped-threads", "all"); - } /* The behavior of this routine with respect to the source flag is: SRC_LINE: Print only source line @@ -4421,9 +4405,10 @@ done: && inferior_thread ()->step_multi)) { if (!ptid_equal (inferior_ptid, null_ptid)) - observer_notify_normal_stop (inferior_thread ()->stop_bpstat); + observer_notify_normal_stop (inferior_thread ()->stop_bpstat, + stop_print_frame); else - observer_notify_normal_stop (NULL); + observer_notify_normal_stop (NULL, stop_print_frame); } if (target_has_execution) diff --git a/gdb/mi/mi-interp.c b/gdb/mi/mi-interp.c index 8e2b230..7f52549 100644 --- a/gdb/mi/mi-interp.c +++ b/gdb/mi/mi-interp.c @@ -52,7 +52,7 @@ static void mi1_command_loop (void); static void mi_insert_notify_hooks (void); static void mi_remove_notify_hooks (void); -static void mi_on_normal_stop (struct bpstats *bs); +static void mi_on_normal_stop (struct bpstats *bs, int print_frame); static void mi_new_thread (struct thread_info *t); static void mi_thread_exit (struct thread_info *t); @@ -322,17 +322,46 @@ mi_inferior_exit (int pid) } static void -mi_on_normal_stop (struct bpstats *bs) +mi_on_normal_stop (struct bpstats *bs, int print_frame) { /* Since this can be called when CLI command is executing, using cli interpreter, be sure to use MI uiout for output, not the current one. */ - struct ui_out *uiout = interp_ui_out (top_level_interpreter ()); + struct ui_out *mi_uiout = interp_ui_out (top_level_interpreter ()); struct mi_interp *mi = top_level_interpreter_data (); + if (print_frame) + { + if (uiout != mi_uiout) + { + /* The normal_stop function has printed frame information into + CLI uiout, or some other non-MI uiout. There's no way we + can extra proper fields from random uiout object, so we print + the frame again. In practice, this can only happen when running + a CLI command in MI. */ + struct ui_out *saved_uiout = uiout; + uiout = mi_uiout; + print_stack_frame (get_selected_frame (NULL), 0, SRC_AND_LOC); + uiout = saved_uiout; + } + + ui_out_field_int (mi_uiout, "thread-id", + pid_to_thread_id (inferior_ptid)); + if (non_stop) + { + struct cleanup *back_to = make_cleanup_ui_out_list_begin_end + (mi_uiout, "stopped-threads"); + ui_out_field_int (mi_uiout, NULL, + pid_to_thread_id (inferior_ptid)); + do_cleanups (back_to); + } + else + ui_out_field_string (mi_uiout, "stopped-threads", "all"); + } + fputs_unfiltered ("*stopped", raw_stdout); - mi_out_put (uiout, raw_stdout); - mi_out_rewind (uiout); + mi_out_put (mi_uiout, raw_stdout); + mi_out_rewind (mi_uiout); fputs_unfiltered ("\n", raw_stdout); gdb_flush (raw_stdout); } diff --git a/gdb/testsuite/lib/mi-support.exp b/gdb/testsuite/lib/mi-support.exp index be9b530..f62c240 100644 --- a/gdb/testsuite/lib/mi-support.exp +++ b/gdb/testsuite/lib/mi-support.exp @@ -1020,13 +1020,13 @@ proc mi_expect_stop { reason func args file line extra test } { set any "\[^\n\]*" - verbose -log "mi_expect_stop: expecting: \\*stopped,${r}${a}${bn}thread-id=\"$decimal\",stopped-threads=$any,frame=\{addr=\"$hex\",func=\"$func\",args=$args,file=\"$any$file\",fullname=\"${fullname_syntax}$file\",line=\"$line\"\}$after_stopped\r\n($thread_selected_re)?$prompt_re" + verbose -log "mi_expect_stop: expecting: \\*stopped,${r}${a}${bn}frame=\{addr=\"$hex\",func=\"$func\",args=$args,file=\"$any$file\",fullname=\"${fullname_syntax}$file\",line=\"$line\"\}$after_stopped,thread-id=\"$decimal\",stopped-threads=$any\r\n($thread_selected_re)?$prompt_re" gdb_expect { - -re "\\*stopped,${r}${a}${bn}thread-id=\"$decimal\",stopped-threads=$any,frame=\{addr=\"$hex\",func=\"$func\",args=$args,file=\"$any$file\",fullname=\"${fullname_syntax}$file\",line=\"($line)\"\}$after_stopped\r\n($thread_selected_re)?$prompt_re" { + -re "\\*stopped,${r}${a}${bn}frame=\{addr=\"$hex\",func=\"$func\",args=$args,file=\"$any$file\",fullname=\"${fullname_syntax}$file\",line=\"($line)\"\}$after_stopped,thread-id=\"$decimal\",stopped-threads=$any\r\n($thread_selected_re)?$prompt_re" { pass "$test" return $expect_out(2,string) } - -re "\\*stopped,${r}${a}${bn}thread-id=\"$decimal\",stopped-threads=$any,frame=\{addr=\"$hex\",func=\"$any\",args=\[\\\[\{\]$any\[\\\]\}\],file=\"$any\",fullname=\"${fullname_syntax}$any\",line=\"\[0-9\]*\"\}$any\r\n$prompt_re" { + -re "\\*stopped,${r}${a}${bn}frame=\{addr=\"$hex\",func=\"$any\",args=\[\\\[\{\]$any\[\\\]\}\],file=\"$any\",fullname=\"${fullname_syntax}$any\",line=\"\[0-9\]*\"\}thread-id=\"$decimal\",stopped-threads=$any\r\n$prompt_re" { verbose -log "got $expect_out(buffer)" fail "$test (stopped at wrong place)" return -1 @@ -1061,9 +1061,9 @@ proc mi_expect_interrupt { test } { set any "\[^\n\]*" # A signal can land anywhere, just ignore the location - verbose -log "mi_expect_interrupt: expecting: \\*stopped,${r},thread-id=\"$decimal\",stopped-threads=$any\r\n$prompt_re" + verbose -log "mi_expect_interrupt: expecting: \\*stopped,${r}$any\r\n$prompt_re" gdb_expect { - -re "\\*stopped,${r},thread-id=\"$decimal\",stopped-threads=$any\r\n$prompt_re" { + -re "\\*stopped,${r}$any\r\n$prompt_re" { pass "$test" return 0; } --Boundary-00=_Oq+iJCqpD0Iidhc--