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