xref: /netbsd-src/external/gpl3/gdb.old/dist/gdb/testsuite/gdb.threads/process-dies-while-detaching.c (revision 6881a4007f077b54e5f51159c52b9b25f57deb0d)
1 /* This testcase is part of GDB, the GNU debugger.
2 
3    Copyright 2016-2023 Free Software Foundation, Inc.
4 
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 3 of the License, or
8    (at your option) any later version.
9 
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14 
15    You should have received a copy of the GNU General Public License
16    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
17 
18 #include <pthread.h>
19 #include <unistd.h>
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <sys/types.h>
23 #include <sys/wait.h>
24 #include <assert.h>
25 #include <errno.h>
26 #include <string.h>
27 
28 /* This barrier ensures we only reach the initial breakpoint after all
29    threads have started.  */
30 pthread_barrier_t start_threads_barrier;
31 
32 /* Many threads in order to be fairly sure the process exits while GDB
33    is detaching from each thread in the process, on targets that need
34    to detach from each thread individually.  */
35 #define NTHREADS 256
36 
37 /* GDB sets a watchpoint here.  */
38 int globalvar = 1;
39 
40 /* GDB reads this.  */
41 int mypid;
42 
43 /* Threads' entry point.  */
44 
45 void *
46 thread_function (void *arg)
47 {
48   pthread_barrier_wait (&start_threads_barrier);
49   _exit (0);
50 }
51 
52 /* The fork child's entry point.  */
53 
54 void
55 child_function (void)
56 {
57   pthread_t threads[NTHREADS];
58   int i;
59 
60   pthread_barrier_init (&start_threads_barrier, NULL, NTHREADS + 1);
61 
62   for (i = 0; i < NTHREADS; i++)
63     pthread_create (&threads[i], NULL, thread_function, NULL);
64   pthread_barrier_wait (&start_threads_barrier);
65 
66   exit (0);
67 }
68 
69 /* This is defined by the .exp file if testing the multi-process
70    variant.  */
71 #ifdef MULTIPROCESS
72 
73 /* The fork parent's entry point.  */
74 
75 void
76 parent_function (pid_t child)
77 {
78   int status, ret;
79 
80   alarm (300);
81 
82   ret = waitpid (child, &status, 0);
83 
84   if (ret == -1)
85     {
86       printf ("waitpid, errno=%d (%s)\n", errno, strerror (errno));
87       exit (1);
88     }
89   else if (WIFEXITED (status))
90     {
91       printf ("exited, status=%d\n", WEXITSTATUS (status));
92       exit (0);
93     }
94   else if (WIFSIGNALED (status))
95     {
96       printf ("signaled, sig=%d\n", WTERMSIG (status));
97       exit (2);
98     }
99   else
100     {
101       printf ("unexpected, status=%x\n", status);
102       exit (3);
103     }
104 }
105 
106 #endif
107 
108 int
109 main (void)
110 {
111 #ifdef MULTIPROCESS
112   pid_t child;
113 
114   child = fork ();
115   if (child == -1)
116     return 1;
117 #endif
118 
119   mypid = getpid ();
120 
121 #ifdef MULTIPROCESS
122   if (child != 0)
123     parent_function (child);
124   else
125 #endif
126     child_function ();
127 
128   /* Not reached.  */
129   abort ();
130 }
131