1 /* Verify that the parent pid is unchanged by __clone_internal.
2    Copyright (C) 2021-2022 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4 
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9 
10    The GNU C Library 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 GNU
13    Lesser General Public License for more details.
14 
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, see
17    <https://www.gnu.org/licenses/>.  */
18 
19 #include <sched.h>
20 #include <signal.h>
21 #include <string.h>
22 #include <stdio.h>
23 #include <unistd.h>
24 #include <sys/types.h>
25 #include <sys/wait.h>
26 #include <clone_internal.h>
27 #include <support/xunistd.h>
28 
29 #ifndef TEST_CLONE_FLAGS
30 #define TEST_CLONE_FLAGS 0
31 #endif
32 
33 static int sig;
34 
35 static int
f(void * a)36 f (void *a)
37 {
38   puts ("in f");
39   union sigval sival;
40   sival.sival_int = getpid ();
41   printf ("pid = %d\n", sival.sival_int);
42   if (sigqueue (getppid (), sig, sival) != 0)
43     return 1;
44   return 0;
45 }
46 
47 
48 static int
do_test(void)49 do_test (void)
50 {
51   int mypid = getpid ();
52 
53   sig = SIGRTMIN;
54   sigset_t ss;
55   sigemptyset (&ss);
56   sigaddset (&ss, sig);
57   if (sigprocmask (SIG_BLOCK, &ss, NULL) != 0)
58     {
59       printf ("sigprocmask failed: %m\n");
60       return 1;
61     }
62 
63 #ifdef __ia64__
64 # define STACK_SIZE 256 * 1024
65 #else
66 # define STACK_SIZE 128 * 1024
67 #endif
68   char st[STACK_SIZE] __attribute__ ((aligned));
69   struct clone_args clone_args =
70     {
71       .flags = TEST_CLONE_FLAGS & ~CSIGNAL,
72       .exit_signal = TEST_CLONE_FLAGS & CSIGNAL,
73       .stack = (uintptr_t) st,
74       .stack_size = sizeof (st),
75     };
76   pid_t p = __clone_internal (&clone_args, f, 0);
77   if (p == -1)
78     {
79       printf("clone failed: %m\n");
80       return 1;
81     }
82   printf ("new thread: %d\n", (int) p);
83 
84   siginfo_t si;
85   do
86     if (sigwaitinfo (&ss, &si) < 0)
87       {
88 	printf("sigwaitinfo failed: %m\n");
89 	kill (p, SIGKILL);
90 	return 1;
91       }
92   while  (si.si_signo != sig || si.si_code != SI_QUEUE);
93 
94   int e;
95   xwaitpid (p, &e, __WCLONE);
96   if (!WIFEXITED (e))
97     {
98       if (WIFSIGNALED (e))
99 	printf ("died from signal %s\n", strsignal (WTERMSIG (e)));
100       else
101 	puts ("did not terminate correctly");
102       return 1;
103     }
104   if (WEXITSTATUS (e) != 0)
105     {
106       printf ("exit code %d\n", WEXITSTATUS (e));
107       return 1;
108     }
109 
110   if (si.si_int != (int) p)
111     {
112       printf ("expected PID %d, got si_int %d\n", (int) p, si.si_int);
113       kill (p, SIGKILL);
114       return 1;
115     }
116 
117   if (si.si_pid != p)
118     {
119       printf ("expected PID %d, got si_pid %d\n", (int) p, (int) si.si_pid);
120       kill (p, SIGKILL);
121       return 1;
122     }
123 
124   if (getpid () != mypid)
125     {
126       puts ("my PID changed");
127       return 1;
128     }
129 
130   return 0;
131 }
132 
133 #include <support/test-driver.c>
134