1 /*
2 * Copyright (c) International Business Machines Corp., 2007
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
10 * the GNU General Public License for more details.
11 * You should have received a copy of the GNU General Public License
12 * along with this program; if not, write to the Free Software
13 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
14 *
15 ***************************************************************************
16 * File: pidns17.c
17 * *
18 * * Description:
19 * * The pidns17.c testcase verifies inside the container, if kill(-1, SIGUSR1)
20 * * terminates all children running inside.
21 * *
22 * * Test Assertion & Strategy:
23 * * Create a PID namespace container.
24 * * Spawn many children inside it.
25 * * Invoke kill(-1, SIGUSR1) inside container and check if it terminates
26 * * all children.
27 * *
28 * * Usage: <for command-line>
29 * * pidns17
30 * *
31 * * History:
32 * * DATE NAME DESCRIPTION
33 * * 13/11/08 Gowrishankar M Creation of this test.
34 * * <gowrishankar.m@in.ibm.com>
35 *
36 ******************************************************************************/
37 #define _GNU_SOURCE 1
38 #include <sys/wait.h>
39 #include <sys/types.h>
40 #include <string.h>
41 #include <stdlib.h>
42 #include <unistd.h>
43 #include <stdio.h>
44 #include <errno.h>
45 #include "pidns_helper.h"
46 #include "test.h"
47
48 char *TCID = "pidns17";
49 int TST_TOTAL = 1;
50
51 int child_fn(void *);
52
53 #define CHILD_PID 1
54 #define PARENT_PID 0
55
56 /*
57 * child_fn() - Inside container
58 */
child_fn(void * arg)59 int child_fn(void *arg)
60 {
61 int children[10], exit_val, i, status;
62 pid_t pid, ppid;
63
64 /* Set process id and parent pid */
65 pid = getpid();
66 ppid = getppid();
67 if (pid != CHILD_PID || ppid != PARENT_PID) {
68 printf("cinit: pidns was not created\n");
69 exit(1);
70 }
71
72 exit_val = 0;
73
74 /* Spawn many children */
75 for (i = 0; i < ARRAY_SIZE(children); i++) {
76 switch ((children[i] = fork())) {
77 case -1:
78 perror("fork failed");
79 exit_val = 1;
80 break;
81 case 0:
82 pause();
83 /* XXX (garrcoop): why exit with an exit code of 2? */
84 exit(2);
85 break;
86 default:
87 /* fork succeeded. */
88 break;
89 }
90 }
91 /* wait for last child to get scheduled */
92 sleep(1);
93
94 if (kill(-1, SIGUSR1) == -1) {
95 perror("cinit: kill(-1, SIGUSR1) failed");
96 exit_val = 1;
97 }
98
99 for (i = 0; i < ARRAY_SIZE(children); i++) {
100 if (waitpid(children[i], &status, 0) == -1) {
101 perror("cinit: waitpid failed");
102 kill(children[i], SIGTERM);
103 waitpid(children[i], &status, 0);
104 exit_val = 1;
105 }
106 if (!(WIFSIGNALED(status) || WTERMSIG(status) == SIGUSR1)) {
107 /*
108 * XXX (garrcoop): this status reporting is overly
109 * noisy. Someone obviously needs to read the
110 * constraints documented in wait(2) a bit more
111 * closely -- in particular the relationship between
112 * WIFEXITED and WEXITSTATUS, and WIFSIGNALED and
113 * WTERMSIG.
114 */
115 printf("cinit: found a child alive still "
116 "%d exit: %d, %d, signal %d, %d", i,
117 WIFEXITED(status), WEXITSTATUS(status),
118 WIFSIGNALED(status), WTERMSIG(status));
119 exit_val = 1;
120 }
121 }
122 if (exit_val == 0)
123 printf("cinit: all children have terminated.\n");
124
125 exit(exit_val);
126 }
127
setup(void)128 static void setup(void)
129 {
130 tst_require_root();
131 check_newpid();
132 }
133
main(int argc,char * argv[])134 int main(int argc, char *argv[])
135 {
136 int status;
137 pid_t pid;
138
139 setup();
140
141 pid = getpid();
142
143 /* Container creation on PID namespace */
144 TEST(do_clone_unshare_test(T_CLONE, CLONE_NEWPID, child_fn, NULL));
145 if (TEST_RETURN == -1) {
146 tst_brkm(TBROK | TERRNO, NULL, "clone failed");
147 }
148
149 sleep(1);
150 if (wait(&status) == -1)
151 tst_resm(TFAIL, "waitpid failed");
152
153 if (WIFEXITED(status) && WEXITSTATUS(status) != 0)
154 tst_resm(TFAIL, "container exited abnormally");
155 else if (WIFSIGNALED(status))
156 tst_resm(TFAIL,
157 "container was signaled with signal = %d",
158 WTERMSIG(status));
159
160 tst_exit();
161
162 }
163