exec_cleanup murder.
authorVladimir Prus <vladimir@codesourcery.com>
Thu, 24 Apr 2008 11:13:44 +0000 (11:13 +0000)
committerVladimir Prus <vladimir@codesourcery.com>
Thu, 24 Apr 2008 11:13:44 +0000 (11:13 +0000)
* breakpoint.c (until_break_command_continuation): Add
the 'error' parameter.  Directly delete the breakoint as
opposed to running cleanups.
(until_break_command): Install continuation only
after starting the target.  Don't use exec cleanups,
use ordinary cleanups.  Discard cleanups is successfully
started the target in async mode.
(make_cleanup_delete_breakpoint): Remove.
* breakpoint.h (make_cleanup_delete_breakpoint): Remove
declaration.
* defs.h (do_exec_cleanups, make_exec_cleanup): Remove
declarations.
(struct continations): Add the 'error' parameter to the
continuation_hook field.
(add_continuation, do_all_continuations)
(add_intermediate_continuation)
(do_all_intermediate_continuations): Add the 'error' parameter.
* exceptions.c (throw_exception): Don't call do_exec_cleanups.
* inf-loop.c (inferior_event_handler): Instead of calling
discard_all_continuations, use do_all_continuations with 1 as
'error' parameter.  Pass 0 as 'error' parameter in existing uses
of discard_all_continuations.
* infcmd.c (step_1): Do not use exec cleanup.  For async case, discard
cleanups.
(step_once): Install continuation only after resuming the target.
(step_1_continuation): Disable longjmp breakpoint on error.
(finish_command_continuation): Add the error parameter.  Delete
the finish breakpoint directly, do not use cleanups.
(finish_command): Do not use exec_cleanups. Always setup
continuation.  For sync case, immediately run them.
(attach_command_continuation): Add the error parameter.
* infrun.c (fetch_inferior_event): Do not use exec cleanups to
remove step_resume_breakpoint -- adjust delete it directly.
* interps.c (interp_set): Adjust call to do_all_continations.
* mi/mi-interp.c (mi_interpreter_exec_continuation): Do not
do exec cleanups.
* mi/mi-main.c (mi_cmd_target_select): Do not do exec
cleanups.
(mi_cmd_execute): Do not use exec_cleanup.
(mi_execute_async_cli_command): Simplify the string concatenation
logic.  Do no use exec cleanup.
(mi_exec_async_cli_cmd_continuation): New parameter error.
Free last_async_command.
* top.c (command_line_handler_continuation): New parameter error.
* utils.c (exec_cleanup_chain, make_exec_cleanup)
(do_exec_cleanups): Remove.
(add_continuation, do_all_continations)
(add_intermediate_continuation)
(do_all_intermediate_continuations): New parameter error.

13 files changed:
gdb/ChangeLog
gdb/breakpoint.c
gdb/breakpoint.h
gdb/defs.h
gdb/exceptions.c
gdb/inf-loop.c
gdb/infcmd.c
gdb/infrun.c
gdb/interps.c
gdb/mi/mi-interp.c
gdb/mi/mi-main.c
gdb/top.c
gdb/utils.c

index 806173c..58c0454 100644 (file)
@@ -1,5 +1,58 @@
 2008-04-24  Vladimir Prus  <vladimir@codesourcery.com>
 
+       exec_cleanup murder.
+       * breakpoint.c (until_break_command_continuation): Add
+       the 'error' parameter.  Directly delete the breakoint as
+       opposed to running cleanups.
+       (until_break_command): Install continuation only
+       after starting the target.  Don't use exec cleanups,
+       use ordinary cleanups.  Discard cleanups is successfully
+       started the target in async mode.
+       (make_cleanup_delete_breakpoint): Remove.
+       * breakpoint.h (make_cleanup_delete_breakpoint): Remove
+       declaration.
+       * defs.h (do_exec_cleanups, make_exec_cleanup): Remove
+       declarations.
+       (struct continations): Add the 'error' parameter to the
+       continuation_hook field.
+       (add_continuation, do_all_continuations)
+       (add_intermediate_continuation)
+       (do_all_intermediate_continuations): Add the 'error' parameter.
+       * exceptions.c (throw_exception): Don't call do_exec_cleanups.
+       * inf-loop.c (inferior_event_handler): Instead of calling
+       discard_all_continuations, use do_all_continuations with 1 as
+       'error' parameter.  Pass 0 as 'error' parameter in existing uses
+       of discard_all_continuations.
+       * infcmd.c (step_1): Do not use exec cleanup.  For async case, discard
+       cleanups.
+       (step_once): Install continuation only after resuming the target.
+       (step_1_continuation): Disable longjmp breakpoint on error.
+       (finish_command_continuation): Add the error parameter.  Delete
+       the finish breakpoint directly, do not use cleanups.
+       (finish_command): Do not use exec_cleanups. Always setup
+       continuation.  For sync case, immediately run them.
+       (attach_command_continuation): Add the error parameter.
+       * infrun.c (fetch_inferior_event): Do not use exec cleanups to
+       remove step_resume_breakpoint -- adjust delete it directly.
+       * interps.c (interp_set): Adjust call to do_all_continations.
+       * mi/mi-interp.c (mi_interpreter_exec_continuation): Do not
+       do exec cleanups.
+       * mi/mi-main.c (mi_cmd_target_select): Do not do exec
+       cleanups.
+       (mi_cmd_execute): Do not use exec_cleanup.
+       (mi_execute_async_cli_command): Simplify the string concatenation
+       logic.  Do no use exec cleanup.
+       (mi_exec_async_cli_cmd_continuation): New parameter error.
+       Free last_async_command.
+       * top.c (command_line_handler_continuation): New parameter error.
+       * utils.c (exec_cleanup_chain, make_exec_cleanup)
+       (do_exec_cleanups): Remove.
+       (add_continuation, do_all_continations)
+       (add_intermediate_continuation)
+       (do_all_intermediate_continuations): New parameter error.
+
+2008-04-24  Vladimir Prus  <vladimir@codesourcery.com>
+
        * breakpoint.h (bp_location_p): New typedef.
        Register a vector of bp_location_p.
        * breakpoint.c (always_inserted_mode)
index 84802ef..2b6e16f 100644 (file)
@@ -64,7 +64,8 @@
 
 /* Prototypes for local functions. */
 
-static void until_break_command_continuation (struct continuation_arg *arg);
+static void until_break_command_continuation (struct continuation_arg *arg, 
+                                             int error);
 
 static void catch_command_1 (char *, int, int);
 
@@ -6130,12 +6131,11 @@ awatch_command (char *arg, int from_tty)
    care of cleaning up the temporary breakpoints set up by the until
    command. */
 static void
-until_break_command_continuation (struct continuation_arg *arg)
+until_break_command_continuation (struct continuation_arg *arg, int error)
 {
-  struct cleanup *cleanups;
-
-  cleanups = (struct cleanup *) arg->data.pointer;
-  do_exec_cleanups (cleanups);
+  delete_breakpoint ((struct breakpoint *)(arg->data.pointer));
+  if (arg->next)
+    delete_breakpoint ((struct breakpoint *)(arg->next->data.pointer));
 }
 
 void
@@ -6146,8 +6146,10 @@ until_break_command (char *arg, int from_tty, int anywhere)
   struct frame_info *frame = get_selected_frame (NULL);
   struct frame_info *prev_frame = get_prev_frame (frame);
   struct breakpoint *breakpoint;
+  struct breakpoint *breakpoint2 = NULL;
   struct cleanup *old_chain;
   struct continuation_arg *arg1;
+  struct continuation_arg *arg2;
 
 
   clear_proceed_status ();
@@ -6183,31 +6185,7 @@ until_break_command (char *arg, int from_tty, int anywhere)
     breakpoint = set_momentary_breakpoint (sal, get_frame_id (frame),
                                           bp_until);
 
-  if (!target_can_async_p ())
-    old_chain = make_cleanup_delete_breakpoint (breakpoint);
-  else
-    old_chain = make_exec_cleanup_delete_breakpoint (breakpoint);
-
-  /* If we are running asynchronously, and the target supports async
-     execution, we are not waiting for the target to stop, in the call
-     tp proceed, below. This means that we cannot delete the
-     brekpoints until the target has actually stopped. The only place
-     where we get a chance to do that is in fetch_inferior_event, so
-     we must set things up for that. */
-
-  if (target_can_async_p ())
-    {
-      /* In this case the arg for the continuation is just the point
-         in the exec_cleanups chain from where to start doing
-         cleanups, because all the continuation does is the cleanups in
-         the exec_cleanup_chain. */
-      arg1 =
-       (struct continuation_arg *) xmalloc (sizeof (struct continuation_arg));
-      arg1->next         = NULL;
-      arg1->data.pointer = old_chain;
-
-      add_continuation (until_break_command_continuation, arg1);
-    }
+  old_chain = make_cleanup_delete_breakpoint (breakpoint);
 
   /* Keep within the current frame, or in frames called by the current
      one.  */
@@ -6215,18 +6193,38 @@ until_break_command (char *arg, int from_tty, int anywhere)
     {
       sal = find_pc_line (get_frame_pc (prev_frame), 0);
       sal.pc = get_frame_pc (prev_frame);
-      breakpoint = set_momentary_breakpoint (sal, get_frame_id (prev_frame),
-                                            bp_until);
-      if (!target_can_async_p ())
-       make_cleanup_delete_breakpoint (breakpoint);
-      else
-       make_exec_cleanup_delete_breakpoint (breakpoint);
+      breakpoint2 = set_momentary_breakpoint (sal, get_frame_id (prev_frame),
+                                             bp_until);
+      make_cleanup_delete_breakpoint (breakpoint2);
     }
 
   proceed (-1, TARGET_SIGNAL_DEFAULT, 0);
-  /* Do the cleanups now, anly if we are not running asynchronously,
-     of if we are, but the target is still synchronous. */
-  if (!target_can_async_p ())
+
+  /* If we are running asynchronously, and proceed call above has actually
+     managed to start the target, arrange for breakpoints to be
+     deleted when the target stops.  Otherwise, we're already stopped and
+     delete breakpoints via cleanup chain.  */
+
+  if (target_can_async_p () && target_executing)
+    {
+      arg1 =
+       (struct continuation_arg *) xmalloc (sizeof (struct continuation_arg));
+      arg1->next         = NULL;
+      arg1->data.pointer = breakpoint;
+
+      if (breakpoint2)
+       {
+         arg2 = (struct continuation_arg *)
+           xmalloc ( sizeof (struct continuation_arg));
+         arg2->next         = NULL;
+         arg2->data.pointer = breakpoint2;
+         arg1->next = arg2;       
+       }
+
+      discard_cleanups (old_chain);
+      add_continuation (until_break_command_continuation, arg1);
+    }
+  else
     do_cleanups (old_chain);
 }
 
@@ -7188,12 +7186,6 @@ make_cleanup_delete_breakpoint (struct breakpoint *b)
   return make_cleanup (do_delete_breakpoint_cleanup, b);
 }
 
-struct cleanup *
-make_exec_cleanup_delete_breakpoint (struct breakpoint *b)
-{
-  return make_exec_cleanup (do_delete_breakpoint_cleanup, b);
-}
-
 void
 delete_command (char *arg, int from_tty)
 {
index ed76f30..83f1cb8 100644 (file)
@@ -700,8 +700,6 @@ extern void breakpoint_init_inferior (enum inf_context);
 
 extern struct cleanup *make_cleanup_delete_breakpoint (struct breakpoint *);
 
-extern struct cleanup *make_exec_cleanup_delete_breakpoint (struct breakpoint *);
-
 extern void delete_breakpoint (struct breakpoint *);
 
 extern void breakpoint_auto_delete (bpstat);
index 2ec9199..2af40ab 100644 (file)
@@ -318,7 +318,6 @@ extern char *safe_strerror (int);
 
 extern void do_cleanups (struct cleanup *);
 extern void do_final_cleanups (struct cleanup *);
-extern void do_exec_cleanups (struct cleanup *);
 
 extern void discard_cleanups (struct cleanup *);
 extern void discard_final_cleanups (struct cleanup *);
@@ -351,8 +350,6 @@ extern struct cleanup *make_final_cleanup (make_cleanup_ftype *, void *);
 extern struct cleanup *make_my_cleanup (struct cleanup **,
                                        make_cleanup_ftype *, void *);
 
-extern struct cleanup *make_exec_cleanup (make_cleanup_ftype *, void *);
-
 extern struct cleanup *save_cleanups (void);
 extern struct cleanup *save_final_cleanups (void);
 extern struct cleanup *save_my_cleanups (struct cleanup **);
@@ -682,7 +679,7 @@ struct continuation_arg
 
 struct continuation
   {
-    void (*continuation_hook) (struct continuation_arg *);
+    void (*continuation_hook) (struct continuation_arg *, int);
     struct continuation_arg *arg_list;
     struct continuation *next;
   };
@@ -693,14 +690,14 @@ extern struct continuation *cmd_continuation;
 extern struct continuation *intermediate_continuation;
 
 /* From utils.c */
-extern void add_continuation (void (*)(struct continuation_arg *),
+extern void add_continuation (void (*)(struct continuation_arg *, int),
                              struct continuation_arg *);
-extern void do_all_continuations (void);
+extern void do_all_continuations (int error);
 extern void discard_all_continuations (void);
 
-extern void add_intermediate_continuation (void (*)(struct continuation_arg *),
+extern void add_intermediate_continuation (void (*)(struct continuation_arg *, int),
                              struct continuation_arg *);
-extern void do_all_intermediate_continuations (void);
+extern void do_all_intermediate_continuations (int error);
 extern void discard_all_intermediate_continuations (void);
 
 /* String containing the current directory (what getwd would return).  */
index 89d1455..304c8c6 100644 (file)
@@ -221,12 +221,6 @@ throw_exception (struct gdb_exception exception)
 
   disable_current_display ();
   do_cleanups (ALL_CLEANUPS);
-  /* When we implement non-stop mode, this should be redone.  If we get
-     exception in a command pertaining to one thread, or maybe even not
-     involving inferior at all, we should not do exec cleanups for all
-     threads.  */
-  if (target_can_async_p () && !target_executing)
-    do_exec_cleanups (ALL_CLEANUPS);
 
   /* Jump to the containing catch_errors() call, communicating REASON
      to that call via setjmp's return value.  Note that REASON can't
index 9519c79..4c61dae 100644 (file)
@@ -50,7 +50,7 @@ inferior_event_handler (enum inferior_event_type event_type,
       printf_unfiltered (_("error detected from target.\n"));
       target_async (NULL, 0);
       pop_target ();
-      discard_all_continuations ();
+      do_all_continuations (1);
       async_enable_stdin ();
       break;
 
@@ -64,7 +64,7 @@ inferior_event_handler (enum inferior_event_type event_type,
        {
          target_async (NULL, 0);
          pop_target ();
-         discard_all_continuations ();
+         do_all_continuations (1);
          async_enable_stdin ();
          display_gdb_prompt (0);
        }
@@ -95,9 +95,9 @@ inferior_event_handler (enum inferior_event_type event_type,
         got interrupted by a breakpoint, still do the pending
         continuations.  The continuation itself is responsible for
         distinguishing the cases.  */
-      do_all_intermediate_continuations ();
+      do_all_intermediate_continuations (0);
 
-      do_all_continuations ();
+      do_all_continuations (0);
 
       if (current_language != expected_language)
        {
@@ -126,7 +126,7 @@ inferior_event_handler (enum inferior_event_type event_type,
     case INF_EXEC_CONTINUE:
       /* Is there anything left to do for the command issued to
          complete? */
-      do_all_intermediate_continuations ();
+      do_all_intermediate_continuations (0);
       break;
 
     case INF_QUIT_REQ: 
index 22a4abb..867dadf 100644 (file)
@@ -72,7 +72,8 @@ static void nofp_registers_info (char *, int);
 static void print_return_value (struct type *func_type,
                                struct type *value_type);
 
-static void finish_command_continuation (struct continuation_arg *);
+static void finish_command_continuation (struct continuation_arg *, 
+                                        int error_p);
 
 static void until_next_command (int);
 
@@ -106,7 +107,7 @@ static void jump_command (char *, int);
 
 static void step_1 (int, int, char *);
 static void step_once (int skip_subroutines, int single_inst, int count);
-static void step_1_continuation (struct continuation_arg *arg);
+static void step_1_continuation (struct continuation_arg *arg, int error_p);
 
 static void next_command (char *, int);
 
@@ -701,7 +702,7 @@ step_1 (int skip_subroutines, int single_inst, char *count_string)
 {
   int count = 1;
   struct frame_info *frame;
-  struct cleanup *cleanups = 0;
+  struct cleanup *cleanups = make_cleanup (null_cleanup, NULL);
   int async_exec = 0;
 
   ERROR_NO_INFERIOR;
@@ -727,10 +728,7 @@ step_1 (int skip_subroutines, int single_inst, char *count_string)
   if (!single_inst || skip_subroutines)                /* leave si command alone */
     {
       enable_longjmp_breakpoint ();
-      if (!target_can_async_p ())
-       cleanups = make_cleanup (disable_longjmp_breakpoint_cleanup, 0 /*ignore*/);
-      else
-        make_exec_cleanup (disable_longjmp_breakpoint_cleanup, 0 /*ignore*/);
+      make_cleanup (disable_longjmp_breakpoint_cleanup, 0 /*ignore*/);
     }
 
   /* In synchronous case, all is well, just use the regular for loop. */
@@ -782,8 +780,7 @@ which has no line number information.\n"), name);
            break;
        }
 
-      if (!single_inst || skip_subroutines)
-       do_cleanups (cleanups);
+      do_cleanups (cleanups);
       return;
     }
   /* In case of asynchronous target things get complicated, do only
@@ -792,8 +789,10 @@ which has no line number information.\n"), name);
      and handle them one at the time, through step_once(). */
   else
     {
-      if (target_can_async_p ())
-       step_once (skip_subroutines, single_inst, count);
+      step_once (skip_subroutines, single_inst, count);
+      /* We are running, and the contination is installed.  It will
+        disable the longjmp breakpoint as appropriate.  */
+      discard_cleanups (cleanups);
     }
 }
 
@@ -803,21 +802,26 @@ which has no line number information.\n"), name);
    proceed(), via step_once(). Basically it is like step_once and
    step_1_continuation are co-recursive. */
 static void
-step_1_continuation (struct continuation_arg *arg)
+step_1_continuation (struct continuation_arg *arg, int error_p)
 {
-  int count;
-  int skip_subroutines;
-  int single_inst;
-
-  skip_subroutines = arg->data.integer;
-  single_inst      = arg->next->data.integer;
-  count            = arg->next->next->data.integer;
-
-  if (stop_step)
-    step_once (skip_subroutines, single_inst, count - 1);
+  if (error_p)
+    disable_longjmp_breakpoint ();
   else
-    if (!single_inst || skip_subroutines)
-      do_exec_cleanups (ALL_CLEANUPS);
+    {
+      int count;
+      int skip_subroutines;
+      int single_inst;
+      
+      skip_subroutines = arg->data.integer;
+      single_inst      = arg->next->data.integer;
+      count            = arg->next->next->data.integer;
+      
+      if (stop_step)
+       step_once (skip_subroutines, single_inst, count - 1);
+      else
+       if (!single_inst || skip_subroutines)
+         disable_longjmp_breakpoint ();
+    }
 }
 
 /* Do just one step operation. If count >1 we will have to set up a
@@ -881,6 +885,7 @@ which has no line number information.\n"), name);
        step_over_calls = STEP_OVER_ALL;
 
       step_multi = (count > 1);
+      proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 1);
       arg1 =
        (struct continuation_arg *) xmalloc (sizeof (struct continuation_arg));
       arg2 =
@@ -894,7 +899,6 @@ which has no line number information.\n"), name);
       arg3->next = NULL;
       arg3->data.integer = count;
       add_intermediate_continuation (step_1_continuation, arg1);
-      proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 1);
     }
 }
 
@@ -1251,7 +1255,7 @@ print_return_value (struct type *func_type, struct type *value_type)
    called via the cmd_continuation pointer.  */
 
 static void
-finish_command_continuation (struct continuation_arg *arg)
+finish_command_continuation (struct continuation_arg *arg, int error_p)
 {
   struct symbol *function;
   struct breakpoint *breakpoint;
@@ -1261,21 +1265,24 @@ finish_command_continuation (struct continuation_arg *arg)
   function = (struct symbol *) arg->next->data.pointer;
   cleanups = (struct cleanup *) arg->next->next->data.pointer;
 
-  if (bpstat_find_breakpoint (stop_bpstat, breakpoint) != NULL
-      && function != NULL)
+  if (!error_p)
     {
-      struct type *value_type;
-
-      value_type = TYPE_TARGET_TYPE (SYMBOL_TYPE (function));
-      if (!value_type)
-       internal_error (__FILE__, __LINE__,
-                       _("finish_command: function has no target type"));
-
-      if (TYPE_CODE (value_type) != TYPE_CODE_VOID)
-       print_return_value (SYMBOL_TYPE (function), value_type); 
+      if (bpstat_find_breakpoint (stop_bpstat, breakpoint) != NULL
+         && function != NULL)
+       {
+         struct type *value_type;
+         
+         value_type = TYPE_TARGET_TYPE (SYMBOL_TYPE (function));
+         if (!value_type)
+           internal_error (__FILE__, __LINE__,
+                           _("finish_command: function has no target type"));
+         
+         if (TYPE_CODE (value_type) != TYPE_CODE_VOID)
+           print_return_value (SYMBOL_TYPE (function), value_type); 
+       }
     }
 
-  do_exec_cleanups (cleanups);
+  delete_breakpoint (breakpoint);
 }
 
 /* "finish": Set a temporary breakpoint at the place the selected
@@ -1326,10 +1333,7 @@ finish_command (char *arg, int from_tty)
 
   breakpoint = set_momentary_breakpoint (sal, get_frame_id (frame), bp_finish);
 
-  if (!target_can_async_p ())
-    old_chain = make_cleanup_delete_breakpoint (breakpoint);
-  else
-    old_chain = make_exec_cleanup_delete_breakpoint (breakpoint);
+  old_chain = make_cleanup_delete_breakpoint (breakpoint);
 
   /* Find the function we will return from.  */
 
@@ -1346,51 +1350,26 @@ finish_command (char *arg, int from_tty)
   proceed_to_finish = 1;       /* We want stop_registers, please...  */
   proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 0);
 
-  /* If running asynchronously and the target support asynchronous
-     execution, set things up for the rest of the finish command to be
-     completed later on, when gdb has detected that the target has
-     stopped, in fetch_inferior_event.  
-     Setup it only after proceed, so that if proceed throws, we don't
-     set continuation.  */
-  if (target_can_async_p ())
-    {
-      arg1 =
-       (struct continuation_arg *) xmalloc (sizeof (struct continuation_arg));
-      arg2 =
-       (struct continuation_arg *) xmalloc (sizeof (struct continuation_arg));
-      arg3 =
-       (struct continuation_arg *) xmalloc (sizeof (struct continuation_arg));
-      arg1->next = arg2;
-      arg2->next = arg3;
-      arg3->next = NULL;
-      arg1->data.pointer = breakpoint;
-      arg2->data.pointer = function;
-      arg3->data.pointer = old_chain;
-      add_continuation (finish_command_continuation, arg1);
-    }
+  arg1 =
+    (struct continuation_arg *) xmalloc (sizeof (struct continuation_arg));
+  arg2 =
+    (struct continuation_arg *) xmalloc (sizeof (struct continuation_arg));
+  arg3 =
+    (struct continuation_arg *) xmalloc (sizeof (struct continuation_arg));
+  arg1->next = arg2;
+  arg2->next = arg3;
+  arg3->next = NULL;
+  arg1->data.pointer = breakpoint;
+  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 ())
-    {
-      /* Did we stop at our breakpoint?  */
-      if (bpstat_find_breakpoint (stop_bpstat, breakpoint) != NULL
-         && function != NULL)
-       {
-         struct type *value_type;
-
-         value_type = TYPE_TARGET_TYPE (SYMBOL_TYPE (function));
-         if (!value_type)
-           internal_error (__FILE__, __LINE__,
-                           _("finish_command: function has no target type"));
-
-         if (TYPE_CODE (value_type) != TYPE_CODE_VOID)
-           print_return_value (SYMBOL_TYPE (function), value_type); 
-       }
-
-      do_cleanups (old_chain);
-    }
+    do_all_continuations (0);
 }
 \f
 
@@ -1936,7 +1915,7 @@ attach_command_post_wait (char *args, int from_tty, int async_exec)
 }
 
 static void
-attach_command_continuation (struct continuation_arg *arg)
+attach_command_continuation (struct continuation_arg *arg, int error_p)
 {
   char *args;
   int from_tty;
index da8c3e0..e47cf1e 100644 (file)
@@ -1073,9 +1073,6 @@ fetch_inferior_event (void *client_data)
 
   if (!async_ecs->wait_some_more)
     {
-      old_cleanups = make_exec_cleanup (delete_step_resume_breakpoint,
-                                       &step_resume_breakpoint);
-
       /* Fill in with reasonable starting values.  */
       init_execution_control_state (async_ecs);
 
@@ -1104,10 +1101,8 @@ fetch_inferior_event (void *client_data)
 
   if (!async_ecs->wait_some_more)
     {
-      /* Do only the cleanups that have been added by this
-         function. Let the continuations for the commands do the rest,
-         if there are any. */
-      do_exec_cleanups (old_cleanups);
+      delete_step_resume_breakpoint (&step_resume_breakpoint);
+
       normal_stop ();
       if (step_multi && stop_step)
        inferior_event_handler (INF_EXEC_CONTINUE, NULL);
index b4c804a..0ebc3f4 100644 (file)
@@ -148,7 +148,7 @@ interp_set (struct interp *interp, int top_level)
 
   if (current_interpreter != NULL)
     {
-      do_all_continuations ();
+      do_all_continuations (0);
       ui_out_flush (uiout);
       if (current_interpreter->procs->suspend_proc
          && !current_interpreter->procs->suspend_proc (current_interpreter->
index c968a8f..8dfd3ee 100644 (file)
@@ -168,9 +168,11 @@ mi_interpreter_prompt_p (void *data)
 }
 
 static void
-mi_interpreter_exec_continuation (struct continuation_arg *arg)
+mi_interpreter_exec_continuation (struct continuation_arg *arg, int error_p)
 {
   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);
@@ -178,7 +180,6 @@ mi_interpreter_exec_continuation (struct continuation_arg *arg)
       fputs_unfiltered ("\n", raw_stdout);
       fputs_unfiltered ("(gdb) \n", raw_stdout);
       gdb_flush (raw_stdout);
-      do_exec_cleanups (ALL_CLEANUPS);
     }
   else if (target_can_async_p ())
     {
index 153d2b5..76e12f3 100644 (file)
@@ -104,7 +104,8 @@ 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);
+static void mi_exec_async_cli_cmd_continuation (struct continuation_arg *arg, 
+                                               int error_p);
 
 static int register_changed_p (int regnum, struct regcache *,
                               struct regcache *);
@@ -684,7 +685,6 @@ mi_cmd_target_select (char *args, int from_tty)
   mi_out_put (uiout, raw_stdout);
   mi_out_rewind (uiout);
   fputs_unfiltered ("\n", raw_stdout);
-  do_exec_cleanups (ALL_CLEANUPS);
   return MI_CMD_QUIET;
 }
 
@@ -1184,6 +1184,8 @@ mi_execute_command (char *cmd, int from_tty)
 static enum mi_cmd_result
 mi_cmd_execute (struct mi_parse *parse)
 {
+  struct cleanup *cleanup;
+  enum mi_cmd_result r;
   free_all_values ();
 
   if (parse->cmd->argv_func != NULL
@@ -1222,11 +1224,19 @@ mi_cmd_execute (struct mi_parse *parse)
            }
        }
       last_async_command = xstrdup (parse->token);
-      make_exec_cleanup (free_current_contents, &last_async_command);
+      cleanup = make_cleanup (free_current_contents, &last_async_command);
       /* FIXME: DELETE THIS! */
       if (parse->cmd->args_func != NULL)
-       return parse->cmd->args_func (parse->args, 0 /*from_tty */ );
-      return parse->cmd->argv_func (parse->command, parse->argv, parse->argc);
+       r = parse->cmd->args_func (parse->args, 0 /*from_tty */ );
+      else
+       r = parse->cmd->argv_func (parse->command, parse->argv, parse->argc);
+      if (target_can_async_p () && target_executing)
+       /* last_async_command will be freed by continuation that
+          all execution command set.  */
+       discard_cleanups (cleanup);
+      else
+       do_cleanups (cleanup);
+      return r;
     }
   else if (parse->cmd->cli.cmd != 0)
     {
@@ -1287,24 +1297,12 @@ mi_execute_async_cli_command (char *mi, char *args, int from_tty)
 {
   struct cleanup *old_cleanups;
   char *run;
-  char *async_args;
 
   if (target_can_async_p ())
-    {
-      async_args = (char *) xmalloc (strlen (args) + 2);
-      make_exec_cleanup (free, async_args);
-      strcpy (async_args, args);
-      strcat (async_args, "&");
-      run = xstrprintf ("%s %s", mi, async_args);
-      make_exec_cleanup (free, run);
-      add_continuation (mi_exec_async_cli_cmd_continuation, NULL);
-      old_cleanups = NULL;
-    }
+    run = xstrprintf ("%s %s&", mi, args);
   else
-    {
-      run = xstrprintf ("%s %s", mi, args);
-      old_cleanups = make_cleanup (xfree, run);
-    }
+    run = xstrprintf ("%s %s", mi, args);
+  old_cleanups = make_cleanup (xfree, run);  
 
   if (!target_can_async_p ())
     {
@@ -1326,11 +1324,24 @@ mi_execute_async_cli_command (char *mi, char *args, int from_tty)
       if (last_async_command)
        fputs_unfiltered (last_async_command, 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 */ );
 
-  if (!target_can_async_p ())
+  if (target_can_async_p ())
+    {
+      /* If we're not executing, an exception should have been throw.  */
+      gdb_assert (target_executing);
+      do_cleanups (old_cleanups);
+    }
+  else
     {
       /* Do this before doing any printing.  It would appear that some
          print code leaves garbage around in the buffer.  */
@@ -1346,13 +1357,14 @@ mi_execute_async_cli_command (char *mi, char *args, int from_tty)
        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)
+mi_exec_async_cli_cmd_continuation (struct continuation_arg *arg, int error_p)
 {
+  /* Assume 'error' means that target is stopped, too.  */
   if (last_async_command)
     fputs_unfiltered (last_async_command, raw_stdout);
   fputs_unfiltered ("*stopped", raw_stdout);
@@ -1360,7 +1372,11 @@ mi_exec_async_cli_cmd_continuation (struct continuation_arg *arg)
   fputs_unfiltered ("\n", raw_stdout);
   fputs_unfiltered ("(gdb) \n", raw_stdout);
   gdb_flush (raw_stdout);
-  do_exec_cleanups (ALL_CLEANUPS);
+  if (last_async_command)
+    {
+      free (last_async_command);
+      last_async_command = NULL;
+    }  
 }
 
 void
index d9b5ce4..2454d24 100644 (file)
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -368,7 +368,7 @@ do_chdir_cleanup (void *old_dir)
    are always running synchronously. Or if we have just executed a
    command that doesn't start the target.  */
 static void
-command_line_handler_continuation (struct continuation_arg *arg)
+command_line_handler_continuation (struct continuation_arg *arg, int error)
 {
   extern int display_time;
   extern int display_space;
@@ -376,6 +376,9 @@ command_line_handler_continuation (struct continuation_arg *arg)
   long time_at_cmd_start  = arg->data.longint;
   long space_at_cmd_start = arg->next->data.longint;
 
+  if (error)
+    return;
+
   bpstat_do_actions (&stop_bpstat);
 
   if (display_time)
index 594fc73..d9953a0 100644 (file)
@@ -104,7 +104,6 @@ static int debug_timestamp = 0;
 
 static struct cleanup *cleanup_chain;  /* cleaned up after a failed command */
 static struct cleanup *final_cleanup_chain;    /* cleaned up when gdb exits */
-static struct cleanup *exec_cleanup_chain;     /* cleaned up on each execution command */
 
 /* Pointer to what is left to do for an execution command after the
    target stops. Used only in asynchronous mode, by targets that
@@ -214,12 +213,6 @@ make_final_cleanup (make_cleanup_ftype *function, void *arg)
   return make_my_cleanup (&final_cleanup_chain, function, arg);
 }
 
-struct cleanup *
-make_exec_cleanup (make_cleanup_ftype *function, void *arg)
-{
-  return make_my_cleanup (&exec_cleanup_chain, function, arg);
-}
-
 static void
 do_freeargv (void *arg)
 {
@@ -316,12 +309,6 @@ do_final_cleanups (struct cleanup *old_chain)
   do_my_cleanups (&final_cleanup_chain, old_chain);
 }
 
-void
-do_exec_cleanups (struct cleanup *old_chain)
-{
-  do_my_cleanups (&exec_cleanup_chain, old_chain);
-}
-
 static void
 do_my_cleanups (struct cleanup **pmy_chain,
                struct cleanup *old_chain)
@@ -440,7 +427,7 @@ null_cleanup (void *arg)
 /* Add a continuation to the continuation list, the global list
    cmd_continuation. The new continuation will be added at the front.*/
 void
-add_continuation (void (*continuation_hook) (struct continuation_arg *),
+add_continuation (void (*continuation_hook) (struct continuation_arg *, int),
                  struct continuation_arg *arg_list)
 {
   struct continuation *continuation_ptr;
@@ -462,7 +449,7 @@ add_continuation (void (*continuation_hook) (struct continuation_arg *),
    and do the continuations from there on, instead of using the
    global beginning of list as our iteration pointer.  */
 void
-do_all_continuations (void)
+do_all_continuations (int error)
 {
   struct continuation *continuation_ptr;
   struct continuation *saved_continuation;
@@ -477,7 +464,7 @@ do_all_continuations (void)
   /* Work now on the list we have set aside.  */
   while (continuation_ptr)
     {
-      (continuation_ptr->continuation_hook) (continuation_ptr->arg_list);
+      (continuation_ptr->continuation_hook) (continuation_ptr->arg_list, error);
       saved_continuation = continuation_ptr;
       continuation_ptr = continuation_ptr->next;
       xfree (saved_continuation);
@@ -504,7 +491,7 @@ discard_all_continuations (void)
    the front.  */
 void
 add_intermediate_continuation (void (*continuation_hook)
-                              (struct continuation_arg *),
+                              (struct continuation_arg *, int),
                               struct continuation_arg *arg_list)
 {
   struct continuation *continuation_ptr;
@@ -526,7 +513,7 @@ add_intermediate_continuation (void (*continuation_hook)
    and do the continuations from there on, instead of using the
    global beginning of list as our iteration pointer.*/
 void
-do_all_intermediate_continuations (void)
+do_all_intermediate_continuations (int error)
 {
   struct continuation *continuation_ptr;
   struct continuation *saved_continuation;
@@ -541,7 +528,7 @@ do_all_intermediate_continuations (void)
   /* Work now on the list we have set aside.  */
   while (continuation_ptr)
     {
-      (continuation_ptr->continuation_hook) (continuation_ptr->arg_list);
+      (continuation_ptr->continuation_hook) (continuation_ptr->arg_list, error);
       saved_continuation = continuation_ptr;
       continuation_ptr = continuation_ptr->next;
       xfree (saved_continuation);