This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[continuation args 2/2] Make continuation args not leak
- From: Pedro Alves <pedro at codesourcery dot com>
- To: gdb-patches at sourceware dot org
- Date: Fri, 11 Jul 2008 21:38:55 +0100
- Subject: [continuation args 2/2] Make continuation args not leak
This is part #2 of a two patch series to does two things:
1) get rid of the crock that was struct continuation_arg, by replacing
it by a void*, and a structure per continuation.
2) Make continuations have a mechanism to free the heap allocated
arguments.
Every time we are adding a continuation, we are allocating its
arguments on the heap. It happens that currently, it isn't defined
who is responsible to free that, so, nobody is doing it...
I'm adding a new argument to add_continuation so the client now
passes a function to be called either:
- after the continuation has ran successfully, or,
- when the continuation is being discarded.
Normally, xfree is passed, but there are some cases that need
to do extra work.
I'm dropping the error_p argument that was passed to the continuation
because:
- it was only called on a really bad error, after poping the current
execution target.
- logically, that case is indistinguishable from discarding
the continuations.
This makes the continuation mechanism very similar to cleanups. In
effect, they can be implemented on top of cleanups, and get rid
of a bunch of duplication. So, I've,
- made a struct continuation an opaque type
- internally consider it a cleanup
- reimplemented the continuations manipulation functions (adding,
running, discarding), on top of the similar cleanup mechanisms.
Tested on x86_64-unknown-linux-gnu {sync,async}.
OK?
--
Pedro Alves
2008-07-11 Pedro Alves <pedro@codesourcery.com>
Rewrite continuations internals on top of cleanups and plug
continuation arguments leaks.
* defs.h (struct continuation): Make it opaque.
(add_continuation, add_intermediate_continuation): Drop the int
argument of the continuation hook argument. Add
continuation_free_args argument.
(do_all_continuations, do_all_intermediate_continuations): Drop
the error_p argument.
* utils.c (add_continuation): Drop the int argument of the
continuation hook argument. Add continuation_free_args argument.
Reimplement on top of cleanups.
(do_all_continuations): Drop error argument. Reimplement on top
of cleanups.
(discard_all_continuations): Reimplement on top of cleanups.
(add_intermediate_continuation): Drop the int argument of the
continuation hook argument. Add continuation_free_args argument.
Reimplement on top of cleanups.
(do_all_intermediate_continuations): Drop error argument.
Reimplement on top of cleanups.
(discard_all_intermediate_continuations): Reimplement on top of
cleanups.
* breakpoint.c (until_break_command_continuation): Drop error
argument. Add xfree as continuation argument deleter.
* inf-loop.c (inferior_event_handler): On error, discard all
continuations. Adjust to new do_all_intermediate_continuations
and do_all_continuations interfaces.
* infcmd.c (step_1_continuation): Drop error_p argument. Adjust.
Pass xfree as continuation argument deleter.
(finish_command_continuation): Drop error_p argument. Adjust.
(finish_command_continuation_free_arg): New.
(finish_command): Pass finish_command_continuation_free_arg as
continuation argument deleter. Adjust to new do_all_continuations
interfaces.
(attach_command_continuation): Drop error_p argument.
(attach_command_continuation_free_args): New.
(attach_command): Pass attach_command_continuation_free_args as
continuation argument deleter.
* interps.c (interp_set): Adjust to new do_all_continuations
interfaces.
* event-top.c (stdin_event_handler): In error, also discard the
intermediate continuations.
---
gdb/breakpoint.c | 7 +---
gdb/defs.h | 17 ++++------
gdb/event-top.c | 1
gdb/inf-loop.c | 12 ++++---
gdb/infcmd.c | 80 +++++++++++++++++++++++++++--------------------
gdb/interps.c | 2 -
gdb/utils.c | 93 ++++++++++++++++++++-----------------------------------
7 files changed, 101 insertions(+), 111 deletions(-)
Index: src/gdb/defs.h
===================================================================
--- src.orig/gdb/defs.h 2008-07-11 21:02:38.000000000 +0100
+++ src/gdb/defs.h 2008-07-11 21:16:58.000000000 +0100
@@ -674,12 +674,7 @@ extern void free_command_lines (struct c
used by the finish and until commands, and in the remote protocol
when opening an extended-remote connection. */
-struct continuation
- {
- void (*continuation_hook) (void *, int);
- void *args;
- struct continuation *next;
- };
+struct continuation;
/* In infrun.c. */
extern struct continuation *cmd_continuation;
@@ -687,12 +682,14 @@ extern struct continuation *cmd_continua
extern struct continuation *intermediate_continuation;
/* From utils.c */
-extern void add_continuation (void (*)(void *, int), void *);
-extern void do_all_continuations (int error);
+extern void add_continuation (void (*)(void *), void *,
+ void (*)(void *));
+extern void do_all_continuations (void);
extern void discard_all_continuations (void);
-extern void add_intermediate_continuation (void (*)(void *, int), void *);
-extern void do_all_intermediate_continuations (int error);
+extern void add_intermediate_continuation (void (*)(void *), void *,
+ void (*)(void *));
+extern void do_all_intermediate_continuations (void);
extern void discard_all_intermediate_continuations (void);
/* String containing the current directory (what getwd would return). */
Index: src/gdb/utils.c
===================================================================
--- src.orig/gdb/utils.c 2008-07-11 21:02:38.000000000 +0100
+++ src/gdb/utils.c 2008-07-11 21:16:58.000000000 +0100
@@ -465,16 +465,16 @@ 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) (void *, int), void *args)
+add_continuation (void (*continuation_hook) (void *), void *args,
+ void (*continuation_free_args) (void *))
{
- struct continuation *continuation_ptr;
+ struct cleanup **as_cleanup_p = (struct cleanup **) &cmd_continuation;
+ make_cleanup_ftype *continuation_hook_ftype = continuation_hook;
- continuation_ptr =
- (struct continuation *) xmalloc (sizeof (struct continuation));
- continuation_ptr->continuation_hook = continuation_hook;
- continuation_ptr->args = args;
- continuation_ptr->next = cmd_continuation;
- cmd_continuation = continuation_ptr;
+ make_my_cleanup2 (as_cleanup_p,
+ *continuation_hook_ftype,
+ args,
+ continuation_free_args);
}
/* Walk down the cmd_continuation list, and execute all the
@@ -486,26 +486,20 @@ add_continuation (void (*continuation_ho
and do the continuations from there on, instead of using the
global beginning of list as our iteration pointer. */
void
-do_all_continuations (int error)
+do_all_continuations (void)
{
- struct continuation *continuation_ptr;
- struct continuation *saved_continuation;
+ struct cleanup *continuation_ptr;
/* Copy the list header into another pointer, and set the global
list header to null, so that the global list can change as a side
- effect of invoking the continuations and the processing of
- the preexisting continuations will not be affected. */
- continuation_ptr = cmd_continuation;
+ effect of invoking the continuations and the processing of the
+ preexisting continuations will not be affected. */
+
+ continuation_ptr = (struct cleanup *) cmd_continuation;
cmd_continuation = NULL;
/* Work now on the list we have set aside. */
- while (continuation_ptr)
- {
- (continuation_ptr->continuation_hook) (continuation_ptr->args, error);
- saved_continuation = continuation_ptr;
- continuation_ptr = continuation_ptr->next;
- xfree (saved_continuation);
- }
+ do_my_cleanups (&continuation_ptr, NULL);
}
/* Walk down the cmd_continuation list, and get rid of all the
@@ -513,14 +507,8 @@ do_all_continuations (int error)
void
discard_all_continuations (void)
{
- struct continuation *continuation_ptr;
-
- while (cmd_continuation)
- {
- continuation_ptr = cmd_continuation;
- cmd_continuation = continuation_ptr->next;
- xfree (continuation_ptr);
- }
+ struct cleanup **continuation_ptr = (struct cleanup **) &cmd_continuation;
+ discard_my_cleanups (continuation_ptr, NULL);
}
/* Add a continuation to the continuation list, the global list
@@ -528,16 +516,16 @@ discard_all_continuations (void)
the front. */
void
add_intermediate_continuation (void (*continuation_hook)
- (void *, int), void *args)
+ (void *), void *args,
+ void (*continuation_free_args) (void *))
{
- struct continuation *continuation_ptr;
+ struct cleanup **as_cleanup_p = (struct cleanup **) &intermediate_continuation;
+ make_cleanup_ftype *continuation_hook_ftype = continuation_hook;
- continuation_ptr =
- (struct continuation *) xmalloc (sizeof (struct continuation));
- continuation_ptr->continuation_hook = continuation_hook;
- continuation_ptr->args = args;
- continuation_ptr->next = intermediate_continuation;
- intermediate_continuation = continuation_ptr;
+ make_my_cleanup2 (as_cleanup_p,
+ *continuation_hook_ftype,
+ args,
+ continuation_free_args);
}
/* Walk down the cmd_continuation list, and execute all the
@@ -549,26 +537,20 @@ add_intermediate_continuation (void (*co
and do the continuations from there on, instead of using the
global beginning of list as our iteration pointer.*/
void
-do_all_intermediate_continuations (int error)
+do_all_intermediate_continuations (void)
{
- struct continuation *continuation_ptr;
- struct continuation *saved_continuation;
+ struct cleanup *continuation_ptr;
/* Copy the list header into another pointer, and set the global
list header to null, so that the global list can change as a side
- effect of invoking the continuations and the processing of
- the preexisting continuations will not be affected. */
- continuation_ptr = intermediate_continuation;
+ effect of invoking the continuations and the processing of the
+ preexisting continuations will not be affected. */
+
+ continuation_ptr = (struct cleanup *) intermediate_continuation;
intermediate_continuation = NULL;
/* Work now on the list we have set aside. */
- while (continuation_ptr)
- {
- (continuation_ptr->continuation_hook) (continuation_ptr->args, error);
- saved_continuation = continuation_ptr;
- continuation_ptr = continuation_ptr->next;
- xfree (saved_continuation);
- }
+ do_my_cleanups (&continuation_ptr, NULL);
}
/* Walk down the cmd_continuation list, and get rid of all the
@@ -576,14 +558,9 @@ do_all_intermediate_continuations (int e
void
discard_all_intermediate_continuations (void)
{
- struct continuation *continuation_ptr;
-
- while (intermediate_continuation)
- {
- continuation_ptr = intermediate_continuation;
- intermediate_continuation = continuation_ptr->next;
- xfree (continuation_ptr);
- }
+ struct cleanup **continuation_ptr
+ = (struct cleanup **) &intermediate_continuation;
+ discard_my_cleanups (continuation_ptr, NULL);
}
Index: src/gdb/breakpoint.c
===================================================================
--- src.orig/gdb/breakpoint.c 2008-07-11 21:02:38.000000000 +0100
+++ src/gdb/breakpoint.c 2008-07-11 21:16:58.000000000 +0100
@@ -62,8 +62,6 @@
/* Prototypes for local functions. */
-static void until_break_command_continuation (void *arg, int error);
-
static void catch_command_1 (char *, int, int);
static void enable_delete_command (char *, int);
@@ -6161,7 +6159,7 @@ struct until_break_command_continuation_
care of cleaning up the temporary breakpoints set up by the until
command. */
static void
-until_break_command_continuation (void *arg, int error)
+until_break_command_continuation (void *arg)
{
struct until_break_command_continuation_args *a = arg;
@@ -6243,7 +6241,8 @@ until_break_command (char *arg, int from
args->breakpoint2 = breakpoint2;
discard_cleanups (old_chain);
- add_continuation (until_break_command_continuation, args);
+ add_continuation (until_break_command_continuation, args,
+ xfree);
}
else
do_cleanups (old_chain);
Index: src/gdb/inf-loop.c
===================================================================
--- src.orig/gdb/inf-loop.c 2008-07-11 21:02:20.000000000 +0100
+++ src/gdb/inf-loop.c 2008-07-11 21:16:58.000000000 +0100
@@ -52,7 +52,8 @@ inferior_event_handler (enum inferior_ev
printf_unfiltered (_("error detected from target.\n"));
target_async (NULL, 0);
pop_target ();
- do_all_continuations (1);
+ discard_all_intermediate_continuations ();
+ discard_all_continuations ();
async_enable_stdin ();
break;
@@ -66,7 +67,8 @@ inferior_event_handler (enum inferior_ev
{
target_async (NULL, 0);
pop_target ();
- do_all_continuations (1);
+ discard_all_intermediate_continuations ();
+ discard_all_continuations ();
async_enable_stdin ();
display_gdb_prompt (0);
}
@@ -96,13 +98,13 @@ inferior_event_handler (enum inferior_ev
touch the inferior memory, e.g. to remove breakpoints, so run
them before running breakpoint commands, which may resume the
target. */
- do_all_intermediate_continuations (0);
+ do_all_intermediate_continuations ();
/* Always finish the previous command before running any
breakpoint commands. Any stop cancels the previous command.
E.g. a "finish" or "step-n" command interrupted by an
unrelated breakpoint is canceled. */
- do_all_continuations (0);
+ do_all_continuations ();
if (current_language != expected_language
&& language_mode == language_mode_auto)
@@ -135,7 +137,7 @@ inferior_event_handler (enum inferior_ev
case INF_EXEC_CONTINUE:
/* Is there anything left to do for the command issued to
complete? */
- do_all_intermediate_continuations (0);
+ do_all_intermediate_continuations ();
break;
case INF_QUIT_REQ:
Index: src/gdb/infcmd.c
===================================================================
--- src.orig/gdb/infcmd.c 2008-07-11 21:02:38.000000000 +0100
+++ src/gdb/infcmd.c 2008-07-11 21:16:58.000000000 +0100
@@ -73,8 +73,6 @@ static void nofp_registers_info (char *,
static void print_return_value (struct type *func_type,
struct type *value_type);
-static void finish_command_continuation (void *args, int error_p);
-
static void until_next_command (int);
static void until_command (char *, int);
@@ -107,7 +105,6 @@ 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, int thread);
-static void step_1_continuation (void *args, int error_p);
static void next_command (char *, int);
@@ -823,15 +820,14 @@ struct step_1_continuation_args
proceed(), via step_once(). Basically it is like step_once and
step_1_continuation are co-recursive. */
static void
-step_1_continuation (void *args, int error_p)
+step_1_continuation (void *args)
{
struct step_1_continuation_args *a = args;
- if (error_p || !step_multi || !stop_step)
+ if (!step_multi || !stop_step)
{
- /* We either hit an error, or stopped for some reason
- that is not stepping, or there are no further steps
- to make. Cleanup. */
+ /* If we stopped for some reason that is not stepping there are
+ no further steps to make. Cleanup. */
if (!a->single_inst || a->skip_subroutines)
delete_longjmp_breakpoint (a->thread);
step_multi = 0;
@@ -906,7 +902,7 @@ which has no line number information.\n"
args->single_inst = single_inst;
args->count = count;
args->thread = thread;
- add_intermediate_continuation (step_1_continuation, args);
+ add_intermediate_continuation (step_1_continuation, args, xfree);
}
}
@@ -1271,35 +1267,43 @@ struct finish_command_continuation_args
};
static void
-finish_command_continuation (void *arg, int error_p)
+finish_command_continuation (void *arg)
{
struct finish_command_continuation_args *a = arg;
- if (!error_p)
+ if (bpstat_find_breakpoint (stop_bpstat, a->breakpoint) != NULL
+ && a->function != NULL)
{
- if (bpstat_find_breakpoint (stop_bpstat, a->breakpoint) != NULL
- && a->function != NULL)
- {
- struct type *value_type;
-
- value_type = TYPE_TARGET_TYPE (SYMBOL_TYPE (a->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 (a->function), 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);
- }
+ struct type *value_type;
+ value_type = TYPE_TARGET_TYPE (SYMBOL_TYPE (a->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 (a->function), value_type);
+ }
+
+ /* We suppress normal call of normal_stop observer and do it here so
+ that that *stopped notification includes the return value. */
+ /* NOTE: This is broken in non-stop mode. There is no guarantee the
+ 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 (stop_bpstat);
suppress_stop_observer = 0;
delete_breakpoint (a->breakpoint);
}
+static void
+finish_command_continuation_free_arg (void *arg)
+{
+ /* NOTE: See finish_command_continuation. This would go away, if
+ this suppressing is made a thread property. */
+ suppress_stop_observer = 0;
+}
+
/* "finish": Set a temporary breakpoint at the place the selected
frame will return to, then continue. */
@@ -1371,11 +1375,12 @@ finish_command (char *arg, int from_tty)
cargs->breakpoint = breakpoint;
cargs->function = function;
- add_continuation (finish_command_continuation, cargs);
+ add_continuation (finish_command_continuation, cargs,
+ finish_command_continuation_free_arg);
discard_cleanups (old_chain);
if (!target_can_async_p ())
- do_all_continuations (0);
+ do_all_continuations ();
}
@@ -1928,12 +1933,20 @@ struct attach_command_continuation_args
};
static void
-attach_command_continuation (void *args, int error_p)
+attach_command_continuation (void *args)
{
struct attach_command_continuation_args *a = args;
attach_command_post_wait (a->args, a->from_tty, a->async_exec);
}
+static void
+attach_command_continuation_free_args (void *args)
+{
+ struct attach_command_continuation_args *a = args;
+ xfree (a->args);
+ xfree (a);
+}
+
void
attach_command (char *args, int from_tty)
{
@@ -2022,7 +2035,8 @@ attach_command (char *args, int from_tty
a->args = xstrdup (args);
a->from_tty = from_tty;
a->async_exec = async_exec;
- add_continuation (attach_command_continuation, a);
+ add_continuation (attach_command_continuation, a,
+ attach_command_continuation_free_args);
return;
}
Index: src/gdb/interps.c
===================================================================
--- src.orig/gdb/interps.c 2008-07-11 21:02:19.000000000 +0100
+++ src/gdb/interps.c 2008-07-11 21:16:58.000000000 +0100
@@ -148,7 +148,7 @@ interp_set (struct interp *interp, int t
if (current_interpreter != NULL)
{
- do_all_continuations (0);
+ do_all_continuations ();
ui_out_flush (uiout);
if (current_interpreter->procs->suspend_proc
&& !current_interpreter->procs->suspend_proc (current_interpreter->
Index: src/gdb/event-top.c
===================================================================
--- src.orig/gdb/event-top.c 2008-07-11 21:02:20.000000000 +0100
+++ src/gdb/event-top.c 2008-07-11 21:16:58.000000000 +0100
@@ -425,6 +425,7 @@ stdin_event_handler (int error, gdb_clie
printf_unfiltered (_("error detected on stdin\n"));
delete_file_handler (input_fd);
discard_all_continuations ();
+ discard_all_intermediate_continuations ();
/* If stdin died, we may as well kill gdb. */
quit_command ((char *) 0, stdin == instream);
}