This is the mail archive of the gdb-patches@sources.redhat.com 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]

Re: [RFA] deleting breakpoints inside of 'commands' (again)


On Mon, 5 Nov 2001, Michael Snyder wrote:

> Fernando Nasser wrote:
> >
> > Don Howard wrote:
> > >
> > > This implementation makes a copy of commands list that contain 'delete'
> > > or 'clear' commands.  It also attempts to clean up when an error in
> > > encountered.  Comments?
>
> Don, I hesitate to say anything, because I know this has been beaten
> to death already, but does this method account for the possibility that
> the list might contain a call to another user command which in turn
> calls "delete" or "clear"?
>


Good point - I should have caught that.  In place of the strncmp()
calls in the previous patch, I've added a call to this:


/* Walk a list of struct command_lines and try to determine if any
   command deletes breakpoints */

int bpstat_actions_delete_breakpoints (struct command_line * cmd)
{
  for (; cmd; cmd = cmd->next)
    {
      int i;

      if (strncmp (cmd->line, "dele", 4) == 0 ||
	  strncmp (cmd->line, "clea", 4) == 0)
	return 1;

      for (i=0; i<cmd->body_count; i++)
	if (bpstat_actions_delete_breakpoints (cmd->body_list[i]))
	  return 1;
    }

  return 0;
}

Comments?



2001-11-05  Don Howard  <dhoward@redhat.com>

        * breakpoint.c (bpstat_do_actions): Avoid deleting a 'commands'
        list while executing that list.  Thanks to Pierre Muller
        <muller@ics.u-strasbg.fr> for suggesting this implementation.
        (cleanup_dup_command_lines): New function.
        (bpstat_actions_delete_breakpoints): Ditto.
        * cli/cli-script.c (dup_command_lines): New function.
        * defs.h: Added declaration of new function.


Index: breakpoint.c
===================================================================
RCS file: /cvs/src/src/gdb/breakpoint.c,v
retrieving revision 1.55
diff -p -u -w -r1.55 breakpoint.c
--- breakpoint.c	2001/10/20 23:54:29	1.55
+++ breakpoint.c	2001/11/06 02:12:39
@@ -1790,6 +1790,36 @@ cleanup_executing_breakpoints (PTR ignor
   executing_breakpoint_commands = 0;
 }

+static void
+cleanup_dup_command_lines (PTR cmds)
+{
+  free_command_lines (cmds);
+}
+
+
+/* Walk a list of struct command_lines and try to determine if any
+   command deletes breakpoints */
+
+static int
+bpstat_actions_delete_breakpoints (struct command_line * cmd)
+{
+  for (; cmd; cmd = cmd->next)
+    {
+      int i;
+
+      if (strncmp (cmd->line, "dele", 4) == 0 ||
+	  strncmp (cmd->line, "clea", 4) == 0)
+	return 1;
+
+      for (i=0; i<cmd->body_count; i++)
+	if (bpstat_actions_delete_breakpoints (cmd->body_list[i]))
+	  return 1;
+    }
+
+  return 0;
+}
+
+
 /* Execute all the commands associated with all the breakpoints at this
    location.  Any of these commands could cause the process to proceed
    beyond this point, etc.  We look out for such changes by checking
@@ -1800,7 +1830,6 @@ bpstat_do_actions (bpstat *bsp)
 {
   bpstat bs;
   struct cleanup *old_chain;
-  struct command_line *cmd;

   /* Avoid endless recursion if a `source' command is contained
      in bs->commands.  */
@@ -1825,16 +1854,37 @@ top:
   breakpoint_proceeded = 0;
   for (; bs != NULL; bs = bs->next)
     {
-      cmd = bs->commands;
-      while (cmd != NULL)
+      struct command_line *cmd;
+      struct cleanup *new_old_chain;
+
+      cmd = 0;
+      new_old_chain = 0;
+
+      /* If the command list for this breakpoint includes a statement
+	 that deletes breakpoints, we assume that the target may be
+	 this breakpoint, so we make a copy of the command list to
+	 avoid walking a list that has been deleted. */
+
+      for (cmd = bs->commands; cmd; cmd = cmd->next)
 	{
+	  if (!new_old_chain && bpstat_actions_delete_breakpoints (cmd))
+	    {
+	      cmd = dup_command_lines (cmd);
+	      new_old_chain = make_cleanup (cleanup_dup_command_lines, cmd);
+	    }
+
 	  execute_control_command (cmd);

 	  if (breakpoint_proceeded)
 	    break;
-	  else
-	    cmd = cmd->next;
 	}
+
+      if (new_old_chain)
+	{
+	  free_command_lines (&cmd);
+	  discard_cleanups (new_old_chain);
+	}
+
       if (breakpoint_proceeded)
 	/* The inferior is proceeded by the command; bomb out now.
 	   The bpstat chain has been blown away by wait_for_inferior.
@@ -1844,6 +1894,7 @@ top:
       else
 	bs->commands = NULL;
     }
+

   executing_breakpoint_commands = 0;
   discard_cleanups (old_chain);
Index: defs.h
===================================================================
RCS file: /cvs/src/src/gdb/defs.h,v
retrieving revision 1.64
diff -p -u -w -r1.64 defs.h
--- defs.h	2001/10/17 20:35:31	1.64
+++ defs.h	2001/11/06 02:12:39
@@ -843,6 +843,7 @@ struct command_line
 extern struct command_line *read_command_lines (char *, int);

 extern void free_command_lines (struct command_line **);
+extern struct command_line * dup_command_lines (struct command_line *);

 /* To continue the execution commands when running gdb asynchronously.
    A continuation structure contains a pointer to a function to be called
Index: cli/cli-script.c
===================================================================
RCS file: /cvs/src/src/gdb/cli/cli-script.c,v
retrieving revision 1.7
diff -p -u -w -r1.7 cli-script.c
--- cli-script.c	2001/06/17 15:16:12	1.7
+++ cli-script.c	2001/11/06 02:12:40
@@ -1005,6 +1005,59 @@ read_command_lines (char *prompt_arg, in
   return (head);
 }

+/* Duplicate a chain of struct command_line's */
+
+struct command_line *
+dup_command_lines (struct command_line *l)
+{
+  struct command_line *dup = NULL;
+  register struct command_line *next = NULL;
+
+
+  for (; l ; l = l->next)
+    {
+      if (next == NULL)
+       {
+         dup = next = (struct command_line *)
+           xmalloc (sizeof (struct command_line));
+       }
+      else
+       {
+         next->next = (struct command_line *)
+           xmalloc (sizeof (struct command_line));
+
+         next = next->next;
+       }
+
+
+      if (next == NULL)
+       return NULL;
+
+
+      next->next = NULL;
+      next->line = xstrdup (l->line);
+      next->control_type = l->control_type;
+      next->body_count = l->body_count;
+
+
+      if (l->body_count > 0)
+       {
+         int i;
+         struct command_line **blist = l->body_list;
+
+         next->body_list =
+           (struct command_line **) xmalloc (sizeof (struct command_line *)
+                                             * l->body_count);
+
+         for (i = 0; i < l->body_count; i++, blist++)
+           next->body_list[i] = dup_command_lines (*blist);
+       }
+    }
+
+  return dup;
+}
+
+
 /* Free a chain of struct command_line's.  */

 void

-- 
-Don
dhoward@redhat.com
gdb engineering



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