1/* Test case for forgotten hw-watchpoints after fork()-off of a process. 2 3 Copyright 2012-2023 Free Software Foundation, Inc. 4 5 This file is part of GDB. 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program; if not, see <http://www.gnu.org/licenses/>. */ 19 20#include "watchpoint-fork.h" 21 22#include <string.h> 23#include <errno.h> 24#include <unistd.h> 25#include <assert.h> 26#include <signal.h> 27#include <stdio.h> 28 29/* `pid_t' may not be available. */ 30 31static volatile int usr1_got; 32 33static void 34handler_usr1 (int signo) 35{ 36 usr1_got++; 37} 38 39void 40forkoff (int nr) 41{ 42 int child, save_parent = getpid (); 43 int i; 44 struct sigaction act, oldact; 45#ifdef THREAD 46 void *thread_result; 47#endif 48 49 memset (&act, 0, sizeof act); 50 act.sa_flags = SA_RESTART; 51 act.sa_handler = handler_usr1; 52 sigemptyset (&act.sa_mask); 53 i = sigaction (SIGUSR1, &act, &oldact); 54 assert (i == 0); 55 56 child = fork (); 57 switch (child) 58 { 59 case -1: 60 assert (0); 61 default: 62#if DEBUG 63 printf ("parent%d: %d\n", nr, (int) child); 64#endif 65 66 /* Sleep for a while to possibly get incorrectly ATTACH_THREADed by GDB 67 tracing the child fork with no longer valid thread/lwp entries of the 68 parent. */ 69 70 i = sleep (2); 71 assert (i == 0); 72 73 /* We must not get caught here (against a forgotten breakpoint). */ 74 75 var++; 76 marker (); 77 78#ifdef THREAD 79 /* And neither got caught our thread. */ 80 81 step = 99; 82 i = pthread_join (thread, &thread_result); 83 assert (i == 0); 84 assert (thread_result == (void *) 99UL); 85#endif 86 87 /* Be sure our child knows we did not get caught above. */ 88 89 i = kill (child, SIGUSR1); 90 assert (i == 0); 91 92 /* Sleep for a while to check GDB's `info threads' no longer tracks us in 93 the child fork. */ 94 95 i = sleep (2); 96 assert (i == 0); 97 98 _exit (0); 99 case 0: 100#if DEBUG 101 printf ("child%d: %d\n", nr, (int) getpid ()); 102#endif 103 104 /* Let the parent signal us about its success. Be careful of races. */ 105 106 for (;;) 107 { 108 /* Parent either died (and USR1_GOT is zero) or it succeeded. */ 109 if (getppid () != save_parent) 110 break; 111 if (kill (getppid (), 0) != 0) 112 break; 113 /* Parent succeeded? */ 114 if (usr1_got) 115 break; 116 117#ifdef THREAD 118 i = pthread_yield (); 119 assert (i == 0); 120#endif 121 } 122 assert (usr1_got); 123 124 /* We must get caught here (against a false watchpoint removal). */ 125 126 marker (); 127 } 128 129 i = sigaction (SIGUSR1, &oldact, NULL); 130 assert (i == 0); 131} 132