This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [RFA] Use observers to report stop events.


Vladimir Prus wrote:

> 
> Presently, the *stopped async output, despite been documented as async,
> is actually output during processing of MI command. Naturally, this is
> not going to work in non-stop mode, since there may be more stops that
> there were MI commands. This patches makes the *stopped output be printed
> via observer. Presently, there's one regression in mi tests -- namely the
> mi-async.exp test -- which uses hardcoded tests for *stopped and so
> fails after update as predicated :-) I'll fix this up later; this is a local
> change and should not affect the review of the patch itself.
> 
> Note that there are no current uses of the normal_stop observer, so this
> patch is as safe as it can get :-)

Ping?

> - Volodya
> 
> * defs.h (make_cleanup_restore_integer): New declaration.
> * utils.c (restore_integer_closure, restore_integer)
> (make_cleanup_restore_integer): New.
> * breakpoint.c (restore_always_inserted_mode): Remove.
> (update_breakpoints_after_exec): Use make_cleanup_restore_integer.
> 
> * inferior.h (suppress_normal_stop_observer): New.
> * infcall.c (call_function_by_hand): Disable stop events when
> doing function calls.
> * infmcd.c (suppress_normal_stop_observer): New.
> (finish_command_continuation): Call normal_stop observer
> explicitly.
> (finish_command): Disable stop events inside proceed.
> * infrun.c (normal_stop): Don't call normal stop observer if
> suppressed of if multi-step is in progress.
> 
> * interps.h (top_level_interpreter): New.
> * interps.c (top_level_interpreter): Rename to
> top_level_interpreter_ptr.
> (top_level_interpreter): New.
> 
> * mi/mi-interp.c (mi_on_normal_stop): New.
> (mi_interpreter_init): Register mi_on_normal_stop.
> (mi_interpreter_exec_continuation): Remove.
> (mi_cmd_interpreter_exec): Don't register the above.
> * mi/mi-main.c (captured_mi_execute_command): Don't care
> about sync_execution.
> (mi_execute_async_cli_command): Don't install continuation.  Don't
> print *stopped.
> (mi_exec_async_cli_cmd_continuation): Remove.
> 
> [gdb/testsuite]
> * gdb.mi/mi-break.exp (test_ignore_count): Adjust stopped pattern.
> * gdb.mi/mi-syn-frame.exp: Use mi_expect_stop instead of direct
> testing of stopped.
> * gdb.mi/mi2-syn-frame.exp: Likewise.
> * lib/mi-support.exp (default_mi_gdb_start): Call detect_async.
> (async, detect_async): New.
> (mi_expect_stop, mi_continue_to_line): Adjust expectation
> depending on if we're running in sync or async mode.
> ---
>  gdb/breakpoint.c                       |   10 +----
>  gdb/defs.h                             |    2 +
>  gdb/infcall.c                          |    6 ++-
>  gdb/infcmd.c                           |   16 +++++--
>  gdb/inferior.h                         |    3 +
>  gdb/infrun.c                           |    3 +-
>  gdb/interps.c                          |   17 ++++++--
>  gdb/interps.h                          |    2 +
>  gdb/mi/mi-interp.c                     |   43 ++++++++++-----------
>  gdb/mi/mi-main.c                       |   36 +----------------
>  gdb/testsuite/gdb.mi/mi-break.exp      |    2 +-
>  gdb/testsuite/gdb.mi/mi-syn-frame.exp  |    6 +--
>  gdb/testsuite/gdb.mi/mi2-syn-frame.exp |   25 +++---------
>  gdb/testsuite/lib/mi-support.exp       |   64 +++++++++++++++++++++++++++++---
>  gdb/utils.c                            |   27 +++++++++++++
>  15 files changed, 157 insertions(+), 105 deletions(-)
> 
> diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
> index d220d00..537b9bf 100644
> --- a/gdb/breakpoint.c
> +++ b/gdb/breakpoint.c
> @@ -1448,12 +1448,6 @@ reattach_breakpoints (int pid)
>    return 0;
>  }
>  
> -static void
> -restore_always_inserted_mode (void *p)
> -{
> -  always_inserted_mode = (uintptr_t) p;
> -}
> -
>  void
>  update_breakpoints_after_exec (void)
>  {
> @@ -1469,9 +1463,7 @@ update_breakpoints_after_exec (void)
>    /* The binary we used to debug is now gone, and we're updating
>       breakpoints for the new binary.  Until we're done, we should not
>       try to insert breakpoints.  */
> -  cleanup = make_cleanup (restore_always_inserted_mode,
> -                       (void *) (uintptr_t) always_inserted_mode);
> -  always_inserted_mode = 0;
> +  cleanup = make_cleanup_restore_integer (&always_inserted_mode, 0);
>  
>    ALL_BREAKPOINTS_SAFE (b, temp)
>    {
> diff --git a/gdb/defs.h b/gdb/defs.h
> index 5c35051..a632840 100644
> --- a/gdb/defs.h
> +++ b/gdb/defs.h
> @@ -345,6 +345,8 @@ extern struct cleanup *make_cleanup_close (int fd);
>  
>  extern struct cleanup *make_cleanup_bfd_close (bfd *abfd);
>  
> +extern struct cleanup *make_cleanup_restore_integer (int *variable, int value);
> +
>  extern struct cleanup *make_final_cleanup (make_cleanup_ftype *, void *);
>  
>  extern struct cleanup *make_my_cleanup (struct cleanup **,
> diff --git a/gdb/infcall.c b/gdb/infcall.c
> index 721b32d..d879b79 100644
> --- a/gdb/infcall.c
> +++ b/gdb/infcall.c
> @@ -706,6 +706,7 @@ call_function_by_hand (struct value *function, int nargs, struct value **args)
>  
>    {
>      struct cleanup *old_cleanups = make_cleanup (null_cleanup, 0);
> +    struct cleanup *old_cleanups2;
>      int saved_async = 0;
>  
>      /* If all error()s out of proceed ended up calling normal_stop
> @@ -718,8 +719,11 @@ call_function_by_hand (struct value *function, int nargs, struct value
> **args)
>  
>      if (target_can_async_p ())
>        saved_async = target_async_mask (0);
> -
> +
> +    old_cleanups2 = make_cleanup_restore_integer
> +      (&suppress_normal_stop_observer, 1);
>      proceed (real_pc, TARGET_SIGNAL_0, 0);
> +    do_cleanups (old_cleanups2);
>      
>      if (saved_async)
>        target_async_mask (saved_async);
> diff --git a/gdb/infcmd.c b/gdb/infcmd.c
> index 2823259..c787f95 100644
> --- a/gdb/infcmd.c
> +++ b/gdb/infcmd.c
> @@ -202,6 +202,9 @@ int step_multi;
>     in format described in environ.h.  */
>  
>  struct gdb_environ *inferior_environ;
> +
> +/* When set, normal_stop will not call the normal_stop observer.  */
> +int suppress_normal_stop_observer = 0;
>  
>  /* Accessor routines. */
>  
> @@ -1275,9 +1278,14 @@ finish_command_continuation (struct continuation_arg *arg, int error)
>  if (TYPE_CODE (value_type) != TYPE_CODE_VOID)
>  print_return_value (value_type);
>  }
> +
> +      /* We suppress normal call of normal_stop observer and do it here so that
> +      that *stopped notification includes the return value.  */
> +      observer_notify_normal_stop (stop_bpstat);
>      }
>  
> -  delete_breakpoint (breakpoint);
> +  suppress_normal_stop_observer = 0;
> +  delete_breakpoint (breakpoint);
>  }
>  
>  /* "finish": Set a temporary breakpoint at the place the selected
> @@ -1343,6 +1351,7 @@ finish_command (char *arg, int from_tty)
>      }
>  
>    proceed_to_finish = 1;     /* We want stop_registers, please...  */
> +  make_cleanup_restore_integer (&suppress_normal_stop_observer, 1);
>    proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 0);
>  
>    arg1 =
> @@ -1358,10 +1367,7 @@ finish_command (char *arg, int from_tty)
>    arg2->data.pointer = function;
>    arg3->data.pointer = old_chain;
>    add_continuation (finish_command_continuation, arg1);
> -
> -  /* Do this only if not running asynchronously or if the target
> -     cannot do async execution.  Otherwise, complete this command when
> -     the target actually stops, in fetch_inferior_event.  */
> +
>    discard_cleanups (old_chain);
>    if (!target_can_async_p ())
>      do_all_continuations (0);
> diff --git a/gdb/inferior.h b/gdb/inferior.h
> index 3aaaa26..630cc52 100644
> --- a/gdb/inferior.h
> +++ b/gdb/inferior.h
> @@ -399,6 +399,9 @@ extern int debug_displaced;
>  void displaced_step_dump_bytes (struct ui_file *file,
>                                  const gdb_byte *buf, size_t len);
>  
> +
> +/* When set, normal_stop will not call the normal_stop observer.  */
> +extern int suppress_normal_stop_observer;
>  
>  /* Possible values for gdbarch_call_dummy_location.  */
>  #define ON_STACK 1
> diff --git a/gdb/infrun.c b/gdb/infrun.c
> index 7f151f7..d6b78ea 100644
> --- a/gdb/infrun.c
> +++ b/gdb/infrun.c
> @@ -3635,7 +3635,8 @@ Further execution is probably impossible.\n"));
>  
>  done:
>    annotate_stopped ();
> -  observer_notify_normal_stop (stop_bpstat);
> +  if (!suppress_normal_stop_observer && !step_multi)
> +    observer_notify_normal_stop (stop_bpstat);
>  }
>  
>  static int
> diff --git a/gdb/interps.c b/gdb/interps.c
> index 9d47843..936fe89 100644
> --- a/gdb/interps.c
> +++ b/gdb/interps.c
> @@ -81,7 +81,7 @@ void _initialize_interpreter (void);
>  
>  static struct interp *interp_list = NULL;
>  static struct interp *current_interpreter = NULL;
> -static struct interp *top_level_interpreter = NULL;
> +static struct interp *top_level_interpreter_ptr = NULL;
>  
>  static int interpreter_initialized = 0;
>  
> @@ -144,7 +144,7 @@ interp_set (struct interp *interp, int top_level)
>    /* If we already have an interpreter, then trying to
>       set top level interpreter is kinda pointless.  */
>    gdb_assert (!top_level || !current_interpreter);
> -  gdb_assert (!top_level || !top_level_interpreter);
> +  gdb_assert (!top_level || !top_level_interpreter_ptr);
>  
>    if (current_interpreter != NULL)
>      {
> @@ -165,7 +165,7 @@ interp_set (struct interp *interp, int top_level)
>  
>    current_interpreter = interp;
>    if (top_level)
> -    top_level_interpreter = interp;
> +    top_level_interpreter_ptr = interp;
>  
>    /* We use interpreter_p for the "set interpreter" variable, so we need
>       to make sure we have a malloc'ed copy for the set command to free. */
> @@ -476,11 +476,18 @@ interpreter_completer (char *text, char *word)
>    return matches;
>  }
>  
> +struct interp *
> +top_level_interpreter (void)
> +{
> +  gdb_assert (top_level_interpreter_ptr);
> +  return top_level_interpreter_ptr;
> +}
> +
>  extern void *
>  top_level_interpreter_data (void)
>  {
> -  gdb_assert (top_level_interpreter);
> -  return top_level_interpreter->data;
> +  gdb_assert (top_level_interpreter_ptr);
> +  return top_level_interpreter_ptr->data;
>  }
>  
>  /* This just adds the "interpreter-exec" command.  */
> diff --git a/gdb/interps.h b/gdb/interps.h
> index e1030fa..5e91080 100644
> --- a/gdb/interps.h
> +++ b/gdb/interps.h
> @@ -64,6 +64,8 @@ extern struct ui_out *interp_ui_out (struct interp *interp);
>  extern int current_interp_named_p (const char *name);
>  extern int current_interp_display_prompt_p (void);
>  extern void current_interp_command_loop (void);
> +/* Returns the top-level interpreter.  */
> +extern struct interp *top_level_interpreter ();
>  /* Returns opaque data associated with the top-level interpreter.  */
>  extern void *top_level_interpreter_data (void);
>  
> diff --git a/gdb/mi/mi-interp.c b/gdb/mi/mi-interp.c
> index ae9e07b..e874a56 100644
> --- a/gdb/mi/mi-interp.c
> +++ b/gdb/mi/mi-interp.c
> @@ -65,6 +65,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_new_thread (struct thread_info *t);
>  
> @@ -88,7 +89,10 @@ mi_interpreter_init (int top_level)
>    mi->event_channel = mi_console_file_new (raw_stdout, "=", 0);
>  
>    if (top_level)
> -    observer_attach_new_thread (mi_new_thread);
> +    {
> +      observer_attach_new_thread (mi_new_thread);
> +      observer_attach_normal_stop (mi_on_normal_stop);
> +    }
>  
>    return mi;
>  }
> @@ -167,26 +171,6 @@ mi_interpreter_prompt_p (void *data)
>    return 0;
>  }
>  
> -static void
> -mi_interpreter_exec_continuation (struct continuation_arg *arg, int  error)
> -{
> -  bpstat_do_actions (&stop_bpstat);
> -  /* It's not clear what to do in the case of errror -- should we assume that
> -     the target is stopped, or that it still runs?  */
> -  if (!target_executing)
> -    {
> -      fputs_unfiltered ("*stopped", raw_stdout);
> -      mi_out_put (uiout, raw_stdout);
> -      fputs_unfiltered ("\n", raw_stdout);
> -      fputs_unfiltered ("(gdb) \n", raw_stdout);
> -      gdb_flush (raw_stdout);
> -    }
> -  else if (target_can_async_p ())
> -    {
> -      add_continuation (mi_interpreter_exec_continuation, NULL);
> -    }
> -}
> -
>  enum mi_cmd_result
>  mi_cmd_interpreter_exec (char *command, char **argv, int argc)
>  {
> @@ -237,7 +221,6 @@ mi_cmd_interpreter_exec (char *command, char **argv, int argc)
>    if (target_can_async_p () && target_executing)
>      {
>        fputs_unfiltered ("^running\n", raw_stdout);
> -      add_continuation (mi_interpreter_exec_continuation, NULL);
>      }
>  
>    if (mi_error_message != NULL)
> @@ -317,6 +300,22 @@ mi_new_thread (struct thread_info *t)
>    gdb_flush (mi->event_channel);
>  }
>  
> +static void
> +mi_on_normal_stop (struct bpstats *bs)
> +{
> +  /* 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 mi_interp *mi = top_level_interpreter_data ();
> +
> +  fputs_unfiltered ("*stopped", raw_stdout);
> +  mi_out_put (uiout, raw_stdout);
> +  mi_out_rewind (uiout);
> +  fputs_unfiltered ("\n", raw_stdout);
> +  gdb_flush (raw_stdout);
> +}
> +
>  extern initialize_file_ftype _initialize_mi_interp; /* -Wmissing-prototypes */
>  
>  void
> diff --git a/gdb/mi/mi-main.c b/gdb/mi/mi-main.c
> index 177d0ec..deb2df9 100644
> --- a/gdb/mi/mi-main.c
> +++ b/gdb/mi/mi-main.c
> @@ -102,9 +102,6 @@ static void mi_execute_cli_command (const char *cmd, int args_p,
>  const char *args);
>  static enum mi_cmd_result mi_execute_async_cli_command (char *mi, char *args, int from_tty);
>  
> -static void mi_exec_async_cli_cmd_continuation (struct continuation_arg *arg,
> -                                             int error);
> -
>  static int register_changed_p (int regnum, struct regcache *,
>  struct regcache *);
>  static void get_register (int regnum, int format);
> @@ -1067,15 +1064,11 @@ captured_mi_execute_command (struct ui_out *uiout, void *data)
>  fputs_unfiltered ("\n", raw_stdout);
>  }
>  else
> +         /* The command does not want anything to be printed.  In that
> +            case, the command probably should not have written anything
> +            to uiout, but in case it has written something, discard it.  */
>  mi_out_rewind (uiout);
>  }
> -      else if (sync_execution)
> -     {
> -       /* Don't print the prompt. We are executing the target in
> -          synchronous mode.  */
> -       args->action = EXECUTE_COMMAND_SUPPRESS_PROMPT;
> -       return;
> -     }
>        break;
>  
>      case CLI_COMMAND:
> @@ -1296,12 +1289,6 @@ mi_execute_async_cli_command (char *mi, char *args, int from_tty)
>  fputs_unfiltered (current_token, raw_stdout);
>        fputs_unfiltered ("^running\n", raw_stdout);
>  
> -      /* Ideally, we should be intalling continuation only when
> -      the target is already running. However, this will break right now,
> -      because continuation installed by the 'finish' command must be after
> -      the continuation that prints *stopped.  This issue will be
> -      fixed soon.  */
> -      add_continuation (mi_exec_async_cli_cmd_continuation, NULL);
>      }
>  
>    execute_command ( /*ui */ run, 0 /*from_tty */ );
> @@ -1317,31 +1304,14 @@ mi_execute_async_cli_command (char *mi, char *args, int from_tty)
>        /* Do this before doing any printing.  It would appear that some
>           print code leaves garbage around in the buffer.  */
>        do_cleanups (old_cleanups);
> -      /* If the target was doing the operation synchronously we fake
> -         the stopped message.  */
> -      fputs_unfiltered ("*stopped", raw_stdout);
> -      mi_out_put (uiout, raw_stdout);
> -      mi_out_rewind (uiout);
>        if (do_timings)
>        print_diff_now (current_command_ts);
> -      fputs_unfiltered ("\n", raw_stdout);
>        return MI_CMD_QUIET;
>      }
>    return MI_CMD_DONE;
>  }
>  
>  void
> -mi_exec_async_cli_cmd_continuation (struct continuation_arg *arg, int error)
> -{
> -  /* Assume 'error' means that target is stopped, too.  */
> -  fputs_unfiltered ("*stopped", raw_stdout);
> -  mi_out_put (uiout, raw_stdout);
> -  fputs_unfiltered ("\n", raw_stdout);
> -  fputs_unfiltered ("(gdb) \n", raw_stdout);
> -  gdb_flush (raw_stdout);
> -}
> -
> -void
>  mi_load_progress (const char *section_name,
>  unsigned long sent_so_far,
>  unsigned long total_section,
> diff --git a/gdb/testsuite/gdb.mi/mi-break.exp b/gdb/testsuite/gdb.mi/mi-break.exp
> index c0f5132..e4fd5c9 100644
> --- a/gdb/testsuite/gdb.mi/mi-break.exp
> +++ b/gdb/testsuite/gdb.mi/mi-break.exp
> @@ -163,7 +163,7 @@ proc test_ignore_count {} {
>      mi_run_cmd
>  
>      gdb_expect {
> -        -re ".*func=\"callme\".*args=\\\[\{name=\"i\",value=\"2\"\}\\\].*\r\n$mi_gdb_prompt$" {
> +        -re
> ".*\\*stopped.*func=\"callme\".*args=\\\[\{name=\"i\",value=\"2\"\}\\\].*\r\n($mi_gdb_prompt)?$" {
>              pass "run to breakpoint with ignore count"
>          }
>          -re ".*$mi_gdb_prompt$" {
> diff --git a/gdb/testsuite/gdb.mi/mi-syn-frame.exp b/gdb/testsuite/gdb.mi/mi-syn-frame.exp
> index ed89965..80d36c9 100644
> --- a/gdb/testsuite/gdb.mi/mi-syn-frame.exp
> +++ b/gdb/testsuite/gdb.mi/mi-syn-frame.exp
> @@ -60,9 +60,7 @@ mi_gdb_test "403-exec-continue" \
>    "403\\^running" \
>    "testing exec continue"
>  
> -# Presently, the *stopped notification for this case does not include
> -# any information.  This can be considered a bug.
> -mi_gdb_test "" "\\*stopped" "finished exec continue"
> +mi_expect_stop "really-no-reason" "" "" "" "" "" "finished exec continue"
>  
>  mi_gdb_test "404-stack-list-frames 0 0" \
>    "404\\^done,stack=\\\[frame=\{level=\"0\",addr=\"$hex\",func=\"main\",file=\".*mi-syn-frame.c\",fullname=\"${fullname_syntax}${srcfile}\",line=\"$decimal\"\}.*\\\]"
>    \
> @@ -91,7 +89,7 @@ mi_gdb_test "407-stack-list-frames" \
>  
>  mi_gdb_test "408-exec-continue" "408\\^running"
>  
> -mi_gdb_test "" ".*\\*stopped.*" "finished exec continue"
> +mi_expect_stop "really-no-reason" "" "" "" "" "" "finished exec continue"
>  
>  mi_gdb_test "409-stack-list-frames 0 0" \
>    "409\\^done,stack=\\\[frame=\{level=\"0\",addr=\"$hex\",func=\"main\",file=\".*mi-syn-frame.c\",fullname=\"${fullname_syntax}${srcfile}\",line=\"$decimal\"\}.*\\\]"
>    \
> diff --git a/gdb/testsuite/gdb.mi/mi2-syn-frame.exp b/gdb/testsuite/gdb.mi/mi2-syn-frame.exp
> index 9c1daab..6e9792a 100644
> --- a/gdb/testsuite/gdb.mi/mi2-syn-frame.exp
> +++ b/gdb/testsuite/gdb.mi/mi2-syn-frame.exp
> @@ -58,15 +58,11 @@ mi_gdb_test "402-stack-list-frames"
> "402\\^done,stack=\\\[frame=\{level=\"0\",ad
>  # Continue back to main()
>  #
>  
> -send_gdb "403-exec-continue\n"
> -gdb_expect {
> -  -re "403\\^running\[\r\n\]+${my_mi_gdb_prompt}.*\\\*stopped\[\r\n\]+${my_mi_gdb_prompt}$" {
> -    pass "403-exec-continue"
> -  }
> -  timeout {
> -    fail "403-exec-continue"
> -  }
> -}
> +mi_gdb_test "403-exec-continue" \
> +  "403\\^running" \
> +  "testing exec continue"
> +
> +mi_expect_stop "really-no-reason" "" "" "" "" "" "finished exec continue"
>  
>  mi_gdb_test "404-stack-list-frames 0 0" \
>    "404\\^done,stack=\\\[frame=\{level=\"0\",addr=\"$hex\",func=\"main\",file=\".*mi-syn-frame.c\",fullname=\"${fullname_syntax}${srcfile}\",line=\"$decimal\"\}.*\\\]"
>    \
> @@ -92,16 +88,9 @@ mi_gdb_test "407-stack-list-frames" \
>    "407\\^done,stack=\\\[frame=\{level=\"0\",addr=\"$hex\",func=\"subroutine\",file=\".*mi-syn-frame.c\",line=\"$decimal\"\},frame=\{level=\"1\",addr=\"$hex\",func=\"handler\",file=\".*mi-syn-frame.c\",line=\"$decimal\"\},frame=\{level=\"2\",addr=\"$hex\",func=\"<signal
>    handler
>   
called>\"\},.*frame=\{level=\"$decimal\",addr=\"$hex\",func=\"have_a_very_merry_interrupt\",file=\".*mi-syn-frame.c\",line=\"$decimal\"\},frame=\{level=\"$decimal\",addr=\"$hex\",func=\"<function
>    called from
>   
gdb>\"\},frame=\{level=\"$decimal\",addr=\"$hex\",func=\"main\",file=\".*mi-syn-frame.c\",line=\"$decimal\"\}.*\\\]"
>    \ "list stack frames"
>  
> +mi_gdb_test "408-exec-continue" "408\\^running"
>  
> -send_gdb "408-exec-continue\n"
> -gdb_expect {
> -  -re "408\\^running\[\r\n\]+${my_mi_gdb_prompt}.*\\\*stopped\[\r\n\]+${my_mi_gdb_prompt}$" {
> -    pass "408-exec-continue"
> -  }
> -  timeout {
> -    fail "408-exec-continue"
> -  }
> -}
> +mi_expect_stop "really-no-reason" "" "" "" "" "" "finished exec continue"
>  
>  mi_gdb_test "409-stack-list-frames 0 0" \
>    "409\\^done,stack=\\\[frame=\{level=\"0\",addr=\"$hex\",func=\"main\",file=\".*mi-syn-frame.c\",fullname=\"${fullname_syntax}${srcfile}\",line=\"$decimal\"\}.*\\\]"
>    \
> diff --git a/gdb/testsuite/lib/mi-support.exp b/gdb/testsuite/lib/mi-support.exp
> index 5926f16..0a6eb8a 100644
> --- a/gdb/testsuite/lib/mi-support.exp
> +++ b/gdb/testsuite/lib/mi-support.exp
> @@ -227,6 +227,8 @@ proc default_mi_gdb_start { args } {
>      }
>      }
>  
> +    detect_async
> +
>      return 0;
>  }
>  
> @@ -911,6 +913,30 @@ proc mi_step { test } {
>    return [mi_step_to {.*} {.*} {.*} {.*} $test]
>  }
>  
> +set async "unknown"
> +
> +proc detect_async {} {
> +    global async
> +    global mi_gdb_prompt
> +
> +    if { $async == "unknown" } {
> +        send_gdb "maint show linux-async\n"
> +
> +     gdb_expect {
> +         -re ".*Controlling the GNU/Linux inferior in asynchronous mode is on...*$mi_gdb_prompt$" {
> +                set async 1
> +         }
> +         -re ".*$mi_gdb_prompt$" {
> +                set async 0
> +         }
> +            timeout {
> +                set async 0
> +            }
> +        }
> +    }
> +    return $async
> +}
> +
>  # Wait for MI *stopped notification to appear.
>  # The REASON, FUNC, ARGS, FILE and LINE are regular expressions
>  # to match against whatever is output in *stopped.  ARGS should
> @@ -933,6 +959,7 @@ proc mi_expect_stop { reason func args file line extra test } {
>      global hex
>      global decimal
>      global fullname_syntax
> +    global async
>  
>      set after_stopped ""
>      set after_reason ""
> @@ -944,10 +971,28 @@ proc mi_expect_stop { reason func args file line extra test } {
>          set after_stopped [lindex $extra 0]
>      }
>  
> +    if {$async} {
> +        set prompt_re ""
> +    } else {
> +        set prompt_re "$mi_gdb_prompt"
> +    }
> +
> +    if { $reason == "really-no-reason" } {
> +        gdb_expect {
> +          -re "\\*stopped\r\n$prompt_re$" {
> +            pass "$test"
> +          }
> +          timeout {
> +              fail "$test (unknown output after running)"
> +          }
> +        }
> +        return
> +    }
> +
>      if { $reason == "exited-normally" } {
>  
>          gdb_expect {
> -          -re "\\*stopped,reason=\"exited-normally\"\r\n$mi_gdb_prompt$" {
> +          -re "\\*stopped,reason=\"exited-normally\"\r\n$prompt_re$" {
>              pass "$test"
>            }
>            -re ".*$mi_gdb_prompt$" {fail "continue to end (2)"}
> @@ -970,17 +1015,17 @@ proc mi_expect_stop { reason func args file line extra test } {
>          set r "reason=\"$reason\","
>      }
>  
> -    verbose -log "mi_expect_stop: expecting:
> .*\\*stopped
${r}${bn}${after_reason}thread-id=\"$decimal\",frame=\{addr=\"$hex\",func=\"$func\",args=$args,file=\".*$file\",fullname=\"${fullname_syntax}$file\",line=\"$line\"\}$after_stopped\r\n$mi_gdb_prompt$"
> +    verbose -log "mi_expect_stop: expecting:
> .*\\*stopped
${r}${bn}${after_reason}thread-id=\"$decimal\",frame=\{addr=\"$hex\",func=\"$func\",args=$args,file=\".*$file\",fullname=\"${fullname_syntax}$file\",line=\"$line\"\}$after_stopped\r\n$prompt_re$"
>      gdb_expect {
> -     -re
> ".*\\*stopped
${r}${bn}${after_reason}thread-id=\"$decimal\",frame=\{addr=\"$hex\",func=\"$func\",args=$args,file=\".*$file\",fullname=\"${fullname_syntax}$file\",line=\"($line)\"\}$after_stopped\r\n$mi_gdb_prompt$"
> {
> +     -re
> ".*\\*stopped
${r}${bn}${after_reason}thread-id=\"$decimal\",frame=\{addr=\"$hex\",func=\"$func\",args=$args,file=\".*$file\",fullname=\"${fullname_syntax}$file\",line=\"($line)\"\}$after_stopped\r\n$prompt_re$"
> {
>  pass "$test"
>              return $expect_out(2,string)
>  }
> -     -re
> ".*\\*stopped
${r}${bn}${after_reason}thread-id=\"$decimal\",frame=\{addr=\"$hex\",func=\".*\",args=\[\\\[\{\].*\[\\\]\}\],file=\".*\",fullname=\"${fullname_syntax}.*\",line=\"\[0-9\]*\"\}.*\r\n$mi_gdb_prompt$"
> {
> +     -re
> ".*\\*stopped
${r}${bn}${after_reason}thread-id=\"$decimal\",frame=\{addr=\"$hex\",func=\".*\",args=\[\\\[\{\].*\[\\\]\}\],file=\".*\",fullname=\"${fullname_syntax}.*\",line=\"\[0-9\]*\"\}.*\r\n$prompt_re$"
> {
>  fail "$test (stopped at wrong place)"
>  return -1
>  }
> -     -re ".*\r\n${mi_gdb_prompt}$" {
> +     -re ".*\r\n$mi_gdb_prompt$" {
>  fail "$test (unknown output after running)"
>  return -1
>  }
> @@ -1337,9 +1382,16 @@ proc mi_continue_to_line {location test} {
>  proc mi_get_stop_line {test} {
>  
>    global mi_gdb_prompt
> +  global async
> +
> +  if {$async} {
> +      set prompt_re ""
> +  } else {
> +      set prompt_re "$mi_gdb_prompt"
> +  }
>  
>    gdb_expect {
> -      -re ".*line=\"(.*)\".*\r\n$mi_gdb_prompt$" {
> +      -re ".*line=\"(.*)\".*\r\n$prompt_re$" {
>            return $expect_out(1,string)
>        }
>        -re ".*$mi_gdb_prompt$" {
> diff --git a/gdb/utils.c b/gdb/utils.c
> index d9953a0..fa8e455 100644
> --- a/gdb/utils.c
> +++ b/gdb/utils.c
> @@ -277,6 +277,33 @@ make_cleanup_free_section_addr_info (struct section_addr_info *addrs)
>    return make_my_cleanup (&cleanup_chain, do_free_section_addr_info, addrs);
>  }
>  
> +struct restore_integer_closure
> +{
> +  int *variable;
> +  int value;
> +};
> +
> +static void
> +restore_integer (void *p)
> +{
> +  struct restore_integer_closure *closure = p;
> +  *(closure->variable) = closure->value;
> +  xfree (closure);
> +}
> +
> +/* Assign VALUE to *VARIABLE and arranges for the old value to
> +   be restored via cleanup.  */
> +struct cleanup *
> +make_cleanup_restore_integer (int *variable, int value)
> +{
> +  struct restore_integer_closure *c =
> +    xmalloc (sizeof (struct restore_integer_closure));
> +  struct cleanup *cleanup = make_cleanup (restore_integer, (void *) c);
> +  c->variable = variable;
> +  c->value = *variable;
> +  *variable = value;
> +  return cleanup;
> +}
>  
>  struct cleanup *
>  make_my_cleanup (struct cleanup **pmy_chain, make_cleanup_ftype *function,



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]