Home | History | Annotate | Line # | Download | only in gdb.threads
      1 /* This testcase is part of GDB, the GNU debugger.
      2 
      3    Copyright 2022-2024 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 <sys/types.h>
     21 #include <sys/wait.h>
     22 #include <errno.h>
     23 #include <assert.h>
     24 #include <limits.h>
     25 
     26 /* Number of threads doing forks.  */
     27 #define N_FORKERS 4
     28 
     29 static void *
     30 forker (void *arg)
     31 {
     32   for (;;)
     33     {
     34       pid_t pid = FORK_FUNC ();
     35 
     36       if (pid == 0)
     37 	_exit (11);
     38 
     39       assert (pid > 0);
     40 
     41       /* Wait for children to exit.  */
     42       int ret;
     43       int stat;
     44       do
     45 	{
     46 	  ret = waitpid (pid, &stat, 0);
     47 	} while (ret == -1 && errno == EINTR);
     48 
     49       assert (ret == pid);
     50       assert (WIFEXITED (stat));
     51       assert (WEXITSTATUS (stat) == 11);
     52 
     53       /* We need a sleep, otherwise the forking threads spam events and the
     54 	 stepping thread doesn't make progress.  Sleep for a bit less than
     55 	 `sleep_a_bit` does, so that forks are likely to interrupt a "next".  */
     56       usleep (40 * 1000);
     57     }
     58 
     59   return NULL;
     60 }
     61 
     62 static void
     63 sleep_a_bit (void)
     64 {
     65   usleep (1000 * 50);
     66 }
     67 
     68 int
     69 main (void)
     70 {
     71   int i;
     72 
     73   alarm (60);
     74 
     75   pthread_t thread[N_FORKERS];
     76   for (i = 0; i < N_FORKERS; ++i)
     77     {
     78       int ret = pthread_create (&thread[i], NULL, forker, NULL);
     79       assert (ret == 0);
     80     }
     81 
     82   for (i = 0; i < INT_MAX; ++i) /* for loop */
     83     {
     84       sleep_a_bit ();  /* break here */
     85       sleep_a_bit ();  /* other line */
     86     }
     87 
     88   for (i = 0; i < N_FORKERS; ++i)
     89     pthread_join (thread[i], NULL);
     90 
     91   return 0;
     92 }
     93