summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog16
-rw-r--r--gdb/breakpoint.c4
-rw-r--r--gdb/defs.h2
-rw-r--r--gdb/exceptions.c4
-rw-r--r--gdb/inf-loop.c4
-rw-r--r--gdb/infrun.c4
-rw-r--r--gdb/testsuite/ChangeLog5
-rw-r--r--gdb/testsuite/gdb.base/commands.exp69
-rw-r--r--gdb/top.c6
-rw-r--r--gdb/utils.c17
10 files changed, 125 insertions, 6 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index e4dfe8ab394..df070d7e631 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,19 @@
+2011-08-26 Jan Kratochvil <jan.kratochvil@redhat.com>
+
+ * breakpoint.c (bpstat_do_actions): New variable cleanup_if_error, call
+ make_bpstat_clear_actions_cleanup and discard_cleanups for it.
+ * defs.h (make_bpstat_clear_actions_cleanup): New declaration.
+ * exceptions.c (throw_exception): Remove the bpstat_clear_actions call.
+ * inf-loop.c (inferior_event_handler): New variable cleanup_if_error,
+ call make_bpstat_clear_actions_cleanup and discard_cleanups for it.
+ Call bpstat_clear_actions for failed fetch_inferior_event_wrapper.
+ * infrun.c (fetch_inferior_event): Call
+ make_bpstat_clear_actions_cleanup.
+ * top.c (execute_command): New variable cleanup_if_error, call
+ make_bpstat_clear_actions_cleanup and discard_cleanups for it.
+ * utils.c (do_bpstat_clear_actions_cleanup)
+ (make_bpstat_clear_actions_cleanup): New functions.
+
2011-08-26 Pedro Alves <pedro@codesourcery.com>
* linux-nat.c (linux_child_follow_fork): Don't set lp->resumed on
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 6ccdb6d015f..8c5b6e5c9ca 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -3352,6 +3352,8 @@ bpstat_do_actions_1 (bpstat *bsp)
void
bpstat_do_actions (void)
{
+ struct cleanup *cleanup_if_error = make_bpstat_clear_actions_cleanup ();
+
/* Do any commands attached to breakpoint we are stopped at. */
while (!ptid_equal (inferior_ptid, null_ptid)
&& target_has_execution
@@ -3363,6 +3365,8 @@ bpstat_do_actions (void)
indicate the inferior was not resumed. */
if (!bpstat_do_actions_1 (&inferior_thread ()->control.stop_bpstat))
break;
+
+ discard_cleanups (cleanup_if_error);
}
/* Print out the (old or new) value associated with a watchpoint. */
diff --git a/gdb/defs.h b/gdb/defs.h
index eaf9c2a5f37..d31e0194e34 100644
--- a/gdb/defs.h
+++ b/gdb/defs.h
@@ -429,6 +429,8 @@ extern const char *gdb_bfd_errmsg (bfd_error_type error_tag, char **matching);
extern int parse_pid_to_attach (char *args);
+extern struct cleanup *make_bpstat_clear_actions_cleanup (void);
+
/* From demangle.c */
extern void set_demangling_style (char *);
diff --git a/gdb/exceptions.c b/gdb/exceptions.c
index e9fdb265553..b9c96beedd8 100644
--- a/gdb/exceptions.c
+++ b/gdb/exceptions.c
@@ -210,10 +210,6 @@ throw_exception (struct gdb_exception exception)
quit_flag = 0;
immediate_quit = 0;
- /* Perhaps it would be cleaner to do this via the cleanup chain (not sure
- I can think of a reason why that is vital, though). */
- bpstat_clear_actions ();
-
do_cleanups (ALL_CLEANUPS);
/* Jump to the containing catch_errors() call, communicating REASON
diff --git a/gdb/inf-loop.c b/gdb/inf-loop.c
index f86b806f37c..3cc2fbab9aa 100644
--- a/gdb/inf-loop.c
+++ b/gdb/inf-loop.c
@@ -42,6 +42,7 @@ inferior_event_handler (enum inferior_event_type event_type,
{
struct gdb_exception e;
int was_sync = 0;
+ struct cleanup *cleanup_if_error = make_bpstat_clear_actions_cleanup ();
switch (event_type)
{
@@ -53,6 +54,7 @@ inferior_event_handler (enum inferior_event_type event_type,
if (!catch_errors (fetch_inferior_event_wrapper,
client_data, "", RETURN_MASK_ALL))
{
+ bpstat_clear_actions ();
do_all_intermediate_continuations (1);
do_all_continuations (1);
async_enable_stdin ();
@@ -142,6 +144,8 @@ inferior_event_handler (enum inferior_event_type event_type,
printf_unfiltered (_("Event type not recognized.\n"));
break;
}
+
+ discard_cleanups (cleanup_if_error);
}
static int
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 3022f9ba19d..27bd3d626af 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -2779,6 +2779,10 @@ fetch_inferior_event (void *client_data)
else
ts_old_chain = make_cleanup (finish_thread_state_cleanup, &ecs->ptid);
+ /* Get executed before make_cleanup_restore_current_thread above to apply
+ still for the thread which has thrown the exception. */
+ make_bpstat_clear_actions_cleanup ();
+
/* Now figure out what to do with the result of the result. */
handle_inferior_event (ecs);
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 5dc374caa26..cfa7227e452 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,5 +1,10 @@
2011-08-26 Jan Kratochvil <jan.kratochvil@redhat.com>
+ * gdb.base/commands.exp (error_clears_commands_left): New function.
+ (): Call it.
+
+2011-08-26 Jan Kratochvil <jan.kratochvil@redhat.com>
+
* gdb.mi/mi-inheritance-syntax-error.cc (A): Make `a' public.
(C): Initialize `a'.
* gdb.mi/mi-inheritance-syntax-error.exp
diff --git a/gdb/testsuite/gdb.base/commands.exp b/gdb/testsuite/gdb.base/commands.exp
index fb9cf4e9d5d..2c579869718 100644
--- a/gdb/testsuite/gdb.base/commands.exp
+++ b/gdb/testsuite/gdb.base/commands.exp
@@ -678,6 +678,74 @@ proc if_commands_test {} {
}
}
+# Verify an error during "commands" commands execution will prevent any other
+# "commands" from other breakpoints at the same location to be executed.
+
+proc error_clears_commands_left {} {
+ set test "hook-stop 1"
+ gdb_test_multiple {define hook-stop} $test {
+ -re "End with a line saying just \"end\"\\.\r\n>$" {
+ pass $test
+ }
+ }
+ set test "hook-stop 1a"
+ gdb_test_multiple {echo hook-stop1\n} $test {
+ -re "\r\n>$" {
+ pass $test
+ }
+ }
+ gdb_test_no_output "end" "hook-stop 1b"
+
+ delete_breakpoints
+ gdb_breakpoint "main"
+
+ set test "main commands 1"
+ gdb_test_multiple {commands $bpnum} $test {
+ -re "End with a line saying just \"end\"\\.\r\n>$" {
+ pass $test
+ }
+ }
+ set test "main commands 1a"
+ gdb_test_multiple {echo cmd1\n} $test {
+ -re "\r\n>$" {
+ pass $test
+ }
+ }
+ set test "main commands 1b"
+ gdb_test_multiple {errorcommandxy\n} $test {
+ -re "\r\n>$" {
+ pass $test
+ }
+ }
+ gdb_test_no_output "end" "main commands 1c"
+
+ gdb_breakpoint "main"
+ set test "main commands 2"
+ gdb_test_multiple {commands $bpnum} $test {
+ -re "End with a line saying just \"end\"\\.\r\n>$" {
+ pass $test
+ }
+ }
+ set test "main commands 2a"
+ gdb_test_multiple {echo cmd2\n} $test {
+ -re "\r\n>$" {
+ pass $test
+ }
+ }
+ set test "main commands 2b"
+ gdb_test_multiple {errorcommandyz\n} $test {
+ -re "\r\n>$" {
+ pass $test
+ }
+ }
+ gdb_test_no_output "end" "main commands 2c"
+
+ gdb_run_cmd
+ gdb_test "" "\r\nhook-stop1\r\n.*\r\ncmd1\r\nUndefined command: \"errorcommandxy\"\\. Try \"help\"\\." "cmd1 error"
+
+ gdb_test {echo idle\n} "\r\nidle" "no cmd2"
+}
+
proc redefine_hook_test {} {
global gdb_prompt
@@ -758,6 +826,7 @@ stray_arg0_test
source_file_with_indented_comment
recursive_source_test
if_commands_test
+error_clears_commands_left
redefine_hook_test
# This one should come last, as it redefines "backtrace".
redefine_backtrace_test
diff --git a/gdb/top.c b/gdb/top.c
index da930ca2889..3112d393203 100644
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -368,12 +368,13 @@ prepare_execute_command (void)
void
execute_command (char *p, int from_tty)
{
- struct cleanup *cleanup;
+ struct cleanup *cleanup_if_error, *cleanup;
struct cmd_list_element *c;
enum language flang;
static int warned = 0;
char *line;
+ cleanup_if_error = make_bpstat_clear_actions_cleanup ();
cleanup = prepare_execute_command ();
/* Force cleanup of any alloca areas if using C alloca instead of
@@ -477,7 +478,8 @@ execute_command (char *p, int from_tty)
}
}
- do_cleanups (cleanup);
+ do_cleanups (cleanup);
+ discard_cleanups (cleanup_if_error);
}
/* Run execute_command for P and FROM_TTY. Capture its output into the
diff --git a/gdb/utils.c b/gdb/utils.c
index 13e99b4e15d..4654870afbc 100644
--- a/gdb/utils.c
+++ b/gdb/utils.c
@@ -3674,6 +3674,23 @@ parse_pid_to_attach (char *args)
return pid;
}
+/* Helper for make_bpstat_clear_actions_cleanup. */
+
+static void
+do_bpstat_clear_actions_cleanup (void *unused)
+{
+ bpstat_clear_actions ();
+}
+
+/* Call bpstat_clear_actions for the case an exception is throw. You should
+ discard_cleanups if no exception is caught. */
+
+struct cleanup *
+make_bpstat_clear_actions_cleanup (void)
+{
+ return make_cleanup (do_bpstat_clear_actions_cleanup, NULL);
+}
+
/* Provide a prototype to silence -Wmissing-prototypes. */
extern initialize_file_ftype _initialize_utils;