+2016-07-01 Pedro Alves <palves@redhat.com>
+
+ * breakpoint.c (breakpoint_init_inferior): Discard watchpoint
+ locations.
+ * infcmd.c (detach_command): Call breakpoint_init_inferior.
+
2016-07-01 Pedro Alves <palves@redhat.com>
* darwin-nat.c (darwin_detach): Use target_announce_detach.
/* Likewise for watchpoints on local expressions. */
if (w->exp_valid_block != NULL)
delete_breakpoint (b);
- else if (context == inf_starting)
+ else
{
- /* Reset val field to force reread of starting value in
- insert_breakpoints. */
- if (w->val)
- value_free (w->val);
- w->val = NULL;
- w->val_valid = 0;
- }
+ /* Get rid of existing locations, which are no longer
+ valid. New ones will be created in
+ update_watchpoint, when the inferior is restarted.
+ The next update_global_location_list call will
+ garbage collect them. */
+ b->loc = NULL;
+
+ if (context == inf_starting)
+ {
+ /* Reset val field to force reread of starting value in
+ insert_breakpoints. */
+ if (w->val)
+ value_free (w->val);
+ w->val = NULL;
+ w->val_valid = 0;
+ }
+ }
}
break;
default:
target_detach (args, from_tty);
+ /* The current inferior process was just detached successfully. Get
+ rid of breakpoints that no longer make sense. Note we don't do
+ this within target_detach because that is also used when
+ following child forks, and in that case we will want to transfer
+ breakpoints to the child, not delete them. */
+ breakpoint_init_inferior (inf_exited);
+
/* If the solist is global across inferiors, don't clear it when we
detach from a single inferior. */
if (!gdbarch_has_global_solist (target_gdbarch ()))
+2016-07-01 Pedro Alves <palves@redhat.com>
+
+ * gdb.multi/watchpoint-multi-exit.c: New file.
+ * gdb.multi/watchpoint-multi-exit.exp: New file.
+
2016-06-30 Pedro Alves <palves@redhat.com>
* lib/gdbserver-support.exp (close_gdbserver, gdb_exit): Don't
--- /dev/null
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2016 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+/* GDB sets watchpoint here. */
+static volatile int globalvar;
+
+/* Whether it's expected that the child exits with a signal, vs
+ exiting normally. GDB sets this. */
+static volatile int expect_signaled;
+
+static void
+marker (void)
+{
+}
+
+static void
+child_function (void)
+{
+}
+
+int
+main (void)
+{
+ pid_t child;
+
+ child = fork ();
+ if (child == -1)
+ exit (1);
+ else if (child != 0)
+ {
+ int status, ret;
+
+ ret = waitpid (child, &status, 0);
+ if (ret == -1)
+ exit (2);
+ else if (expect_signaled && !WIFSIGNALED (status))
+ exit (3);
+ else if (!expect_signaled && !WIFEXITED (status))
+ exit (4);
+ else
+ marker ();
+ }
+ else
+ child_function ();
+
+ exit (0);
+}
--- /dev/null
+# Copyright 2016 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# Make sure that if an inferior exits or is detached/killed, its
+# watchpoints don't end up with stale locations, preventing resumption
+# of other inferiors.
+
+standard_testfile
+
+if {[build_executable "failed to build" $testfile $srcfile {debug}]} {
+ return -1
+}
+
+# The test proper. DISPOSE indicates how to dispose of the fork
+# child. Can be either "kill", "detach", or "exit" (to continue it to
+# normal exit).
+proc do_test {dispose} {
+ global binfile
+
+ clean_restart $binfile
+
+ gdb_test_no_output "set follow-fork child"
+ gdb_test_no_output "set detach-on-fork off"
+
+ if ![runto "child_function"] {
+ fail "Can't run to child_function"
+ return
+ }
+
+ gdb_test "watch globalvar" "atchpoint \[0-9\]+: globalvar" \
+ "set watchpoint on inferior 2"
+
+ # Dispose of the inferior. This should get rid of this inferior's
+ # watchpoint locations.
+ if {$dispose == "kill"} {
+ gdb_test "kill" "" "kill inferior 2" \
+ "Kill the program being debugged.*y or n. $" "y"
+ } elseif {$dispose == "detach"} {
+ gdb_test "detach" ".*" "detach inferior 2"
+ } elseif {$dispose == "exit"} {
+ gdb_test "continue" ".*exited normally.*" "run to exit inferior 2"
+ } else {
+ perror "unhandled dispose: $dispose"
+ }
+
+ gdb_test "inferior 1" "witching to inferior 1 .*" \
+ "switch back to inferior 1"
+
+ if {$dispose == "kill"} {
+ gdb_test "print expect_signaled = 1" " = 1"
+ }
+
+ gdb_breakpoint "marker"
+
+ # Now continue inferior 1. Before GDB was fixed, watchpoints for
+ # inferior 2 managed to be left behind. When GDB realized that
+ # they hadn't been inserted, the continue command was aborted:
+ #
+ # (gdb) continue
+ # Continuing.
+ # Warning:
+ # Could not insert hardware watchpoint 2.
+ # Could not insert hardware breakpoints:
+ # You may have requested too many hardware breakpoints/watchpoints.
+ #
+ # Command aborted.
+ # (gdb)
+ #
+ gdb_test "continue" "Breakpoint \[0-9\]+, marker .*" \
+ "continue in inferior 1"
+}
+
+foreach_with_prefix dispose {"kill" "detach" "exit"} {
+ do_test $dispose
+}