diff options
author | Jan Kratochvil <jan.kratochvil@redhat.com> | 2012-01-24 13:46:55 +0000 |
---|---|---|
committer | Jan Kratochvil <jan.kratochvil@redhat.com> | 2012-01-24 13:46:55 +0000 |
commit | 4403d8e9b35649c5b24f65c0ec0decc3839e1164 (patch) | |
tree | 05ba9cdf77784672a115e5576715b31fc7df7873 /gdb/testsuite/gdb.threads/watchpoint-fork-child.c | |
parent | 2992c9a7112fd3b97cd693b743639e01baea3003 (diff) | |
download | binutils-4403d8e9b35649c5b24f65c0ec0decc3839e1164.zip binutils-4403d8e9b35649c5b24f65c0ec0decc3839e1164.tar.gz binutils-4403d8e9b35649c5b24f65c0ec0decc3839e1164.tar.bz2 |
gdb/
Fix watchpoints across inferior fork.
* amd64-linux-nat.c (update_debug_registers_callback): Update the
comment for linux_nat_iterate_watchpoint_lwps.
(amd64_linux_dr_set_control, amd64_linux_dr_set_addr): Use
linux_nat_iterate_watchpoint_lwps.
(amd64_linux_prepare_to_resume): New comment on Linux kernel.
* i386-linux-nat.c (update_debug_registers_callback): Update the
comment for linux_nat_iterate_watchpoint_lwps.
(i386_linux_dr_set_control, i386_linux_dr_set_addr): Use
linux_nat_iterate_watchpoint_lwps.
(i386_linux_prepare_to_resume): New comment on Linux kernel.
* i386-nat.c: Include inferior.h.
(dr_mirror): Remove.
(i386_inferior_data, struct i386_inferior_data)
(i386_inferior_data_get): New.
(i386_debug_reg_state): Use i386_inferior_data_get.
(i386_cleanup_dregs, i386_update_inferior_debug_regs)
(i386_insert_watchpoint, i386_remove_watchpoint)
(i386_stopped_data_address, i386_insert_hw_breakpoint)
(i386_remove_hw_breakpoint): New variable state, use
i386_debug_reg_state instead of DR_MIRROR.
* linux-nat.c (delete_lwp): New declaration.
(num_lwps): Move here from downwards.
(delete_lwp_cleanup): New.
(linux_child_follow_fork): Create new child_lp, call
linux_nat_new_thread and linux_nat_prepare_to_resume before calling
PTRACE_DETACH.
(num_lwps): Move upwards.
(linux_nat_iterate_watchpoint_lwps): New.
* linux-nat.h (linux_nat_iterate_watchpoint_lwps_ftype): New.
(linux_nat_iterate_watchpoint_lwps_ftype): New declaration.
gdb/testsuite/
Fix watchpoints across inferior fork.
* gdb.threads/watchpoint-fork-child.c: New file.
* gdb.threads/watchpoint-fork-mt.c: New file.
* gdb.threads/watchpoint-fork-parent.c: New file.
* gdb.threads/watchpoint-fork-st.c: New file.
* gdb.threads/watchpoint-fork.exp: New file.
* gdb.threads/watchpoint-fork.h: New file.
Diffstat (limited to 'gdb/testsuite/gdb.threads/watchpoint-fork-child.c')
-rw-r--r-- | gdb/testsuite/gdb.threads/watchpoint-fork-child.c | 129 |
1 files changed, 129 insertions, 0 deletions
diff --git a/gdb/testsuite/gdb.threads/watchpoint-fork-child.c b/gdb/testsuite/gdb.threads/watchpoint-fork-child.c new file mode 100644 index 0000000..7a7e07f --- /dev/null +++ b/gdb/testsuite/gdb.threads/watchpoint-fork-child.c @@ -0,0 +1,129 @@ +/* Test case for forgotten hw-watchpoints after fork()-off of a process. + + Copyright 2012 Free Software Foundation, Inc. + + This file is part of GDB. + + 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <string.h> +#include <errno.h> +#include <unistd.h> +#include <assert.h> +#include <signal.h> +#include <stdio.h> + +#include "watchpoint-fork.h" + +/* `pid_t' may not be available. */ + +static volatile int usr1_got; + +static void +handler_usr1 (int signo) +{ + usr1_got++; +} + +void +forkoff (int nr) +{ + int child, save_parent = getpid (); + int i; + struct sigaction act, oldact; +#ifdef THREAD + void *thread_result; +#endif + + memset (&act, 0, sizeof act); + act.sa_flags = SA_RESTART; + act.sa_handler = handler_usr1; + sigemptyset (&act.sa_mask); + i = sigaction (SIGUSR1, &act, &oldact); + assert (i == 0); + + child = fork (); + switch (child) + { + case -1: + assert (0); + default: + printf ("parent%d: %d\n", nr, (int) child); + + /* Sleep for a while to possibly get incorrectly ATTACH_THREADed by GDB + tracing the child fork with no longer valid thread/lwp entries of the + parent. */ + + i = sleep (2); + assert (i == 0); + + /* We must not get caught here (against a forgotten breakpoint). */ + + var++; + marker (); + +#ifdef THREAD + /* And neither got caught our thread. */ + + step = 99; + i = pthread_join (thread, &thread_result); + assert (i == 0); + assert (thread_result == (void *) 99UL); +#endif + + /* Be sure our child knows we did not get caught above. */ + + i = kill (child, SIGUSR1); + assert (i == 0); + + /* Sleep for a while to check GDB's `info threads' no longer tracks us in + the child fork. */ + + i = sleep (2); + assert (i == 0); + + _exit (0); + case 0: + printf ("child%d: %d\n", nr, (int) getpid ()); + + /* Let the parent signal us about its success. Be careful of races. */ + + for (;;) + { + /* Parent either died (and USR1_GOT is zero) or it succeeded. */ + if (getppid () != save_parent) + break; + if (kill (getppid (), 0) != 0) + break; + /* Parent succeeded? */ + if (usr1_got) + break; + +#ifdef THREAD + i = pthread_yield (); + assert (i == 0); +#endif + } + assert (usr1_got); + + /* We must get caught here (against a false watchpoint removal). */ + + marker (); + } + + i = sigaction (SIGUSR1, &oldact, NULL); + assert (i == 0); +} |