blob: 13cdabb539607be3e7a7d16b6db2f314eb5c4e9e [file] [log] [blame]
robbiew906d4682003-01-06 17:23:07 +00001/*
2 *
3 * Copyright (c) International Business Machines Corp., 2002
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 2 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
13 * the 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, write to the Free Software
Wanlong Gao4548c6c2012-10-19 18:03:36 +080017 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
robbiew906d4682003-01-06 17:23:07 +000018 */
19
20/*
21 * NAME
22 * pipe04.c
23 *
24 * DESCRIPTION
25 * Check that processes are killable, even when they are still writing
26 * data to a pipe.
27 *
28 * ALGORITHM
29 * 1. Open a pipe
30 * 2. fork a two children that will write to the pipe
31 * 3. read a bit from both children
32 * 3. kill both children and wait to make sure they die
33 *
34 * USAGE: <for command-line>
35 * pipe04 [-c n] [-f] [-i n] [-I x] [-P x] [-t]
36 * where, -c n : Run n copies concurrently.
37 * -f : Turn off functionality Testing.
38 * -i n : Execute test n times.
39 * -I x : Execute test for x seconds.
40 * -P x : Pause for x seconds between iterations.
41 * -t : Turn on syscall timing.
42 *
43 * HISTORY
44 * 11/2002 Ported by Paul Larson
45 */
46#include <unistd.h>
47#include <errno.h>
48#include <signal.h>
49#include <sys/types.h>
50#include <sys/wait.h>
51#include "test.h"
robbiew906d4682003-01-06 17:23:07 +000052
53char *TCID = "pipe04";
54int TST_TOTAL = 1;
robbiew906d4682003-01-06 17:23:07 +000055
robbiew906d4682003-01-06 17:23:07 +000056int fildes[2]; /* fds for pipe read and write */
57
58void setup(void);
59void cleanup(void);
60void c1func(void);
61void c2func(void);
62void alarmfunc(int);
63
robbiewa728d282003-09-08 21:36:41 +000064ssize_t safe_read(int fd, void *buf, size_t count)
65{
66 ssize_t n;
67
68 do {
69 n = read(fd, buf, count);
70 } while (n < 0 && errno == EINTR);
71
72 return n;
73}
74
robbiew906d4682003-01-06 17:23:07 +000075int main(int ac, char **av)
76{
Cyril Hrubis89af32a2012-10-24 16:39:11 +020077 int lc;
Cyril Hrubis0b9589f2014-05-27 17:40:33 +020078 const char *msg;
robbiew906d4682003-01-06 17:23:07 +000079 pid_t c1pid, c2pid;
Garrett Cooperc452c252010-12-19 10:12:42 -080080 int wtstatus;
robbiew906d4682003-01-06 17:23:07 +000081 int bytesread;
subrata_modak56207ce2009-03-23 13:35:39 +000082 int acnt = 0, bcnt = 0;
robbiew906d4682003-01-06 17:23:07 +000083
84 char rbuf[BUFSIZ];
85
Garrett Cooper53740502010-12-16 00:04:01 -080086 if ((msg = parse_opts(ac, av, NULL, NULL)) != NULL)
Garrett Cooper60fa8012010-11-22 13:50:58 -080087 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
robbiewd34d5812005-07-11 22:28:09 +000088#ifdef UCLINUX
89 maybe_run_child(&c1func, "ndd", 1, &fildes[0], &fildes[1]);
90 maybe_run_child(&c2func, "ndd", 2, &fildes[0], &fildes[1]);
91#endif
92
robbiew906d4682003-01-06 17:23:07 +000093 setup();
94
95 for (lc = 0; TEST_LOOPING(lc); lc++) {
96
Caspar Zhangd59a6592013-03-07 14:59:12 +080097 /* reset tst_count in case we are looping */
98 tst_count = 0;
robbiew906d4682003-01-06 17:23:07 +000099
100 if (pipe(fildes) == -1)
subrata_modak4bb656a2009-02-26 12:02:09 +0000101 tst_brkm(TBROK, cleanup, "pipe() failed - errno %d",
subrata_modak56207ce2009-03-23 13:35:39 +0000102 errno);
robbiew906d4682003-01-06 17:23:07 +0000103
robbiewd34d5812005-07-11 22:28:09 +0000104 if ((c1pid = FORK_OR_VFORK()) == -1)
subrata_modak56207ce2009-03-23 13:35:39 +0000105 tst_brkm(TBROK, cleanup, "fork() failed - "
106 "errno %d", errno);
robbiew906d4682003-01-06 17:23:07 +0000107 if (c1pid == 0)
robbiewd34d5812005-07-11 22:28:09 +0000108#ifdef UCLINUX
subrata_modak56207ce2009-03-23 13:35:39 +0000109 if (self_exec(av[0], "ndd", 1, fildes[0], fildes[1]) <
110 0) {
robbiewd34d5812005-07-11 22:28:09 +0000111 tst_brkm(TBROK, cleanup, "self_exec failed");
112 }
113#else
robbiew906d4682003-01-06 17:23:07 +0000114 c1func();
robbiewd34d5812005-07-11 22:28:09 +0000115#endif
subrata_modak56207ce2009-03-23 13:35:39 +0000116 if ((c2pid = FORK_OR_VFORK()) == -1)
117 tst_brkm(TBROK, cleanup, "fork() failed - "
118 "errno %d", errno);
robbiew906d4682003-01-06 17:23:07 +0000119 if (c2pid == 0)
robbiewd34d5812005-07-11 22:28:09 +0000120#ifdef UCLINUX
subrata_modak56207ce2009-03-23 13:35:39 +0000121 if (self_exec(av[0], "ndd", 2, fildes[0], fildes[1]) <
122 0) {
robbiewd34d5812005-07-11 22:28:09 +0000123 tst_brkm(TBROK, cleanup, "self_exec failed");
124 }
125#else
robbiew906d4682003-01-06 17:23:07 +0000126 c2func();
robbiewd34d5812005-07-11 22:28:09 +0000127#endif
robbiew906d4682003-01-06 17:23:07 +0000128
129 /* PARENT */
130 if (close(fildes[1]) == -1)
131 tst_resm(TWARN, "Could not close fildes[1] - errno %d",
subrata_modak56207ce2009-03-23 13:35:39 +0000132 errno);
robbiew906d4682003-01-06 17:23:07 +0000133 /*
134 * Read a bit from the children first
135 */
subrata_modak56207ce2009-03-23 13:35:39 +0000136 while ((acnt < 100) && (bcnt < 100)) {
robbiewa728d282003-09-08 21:36:41 +0000137 bytesread = safe_read(fildes[0], rbuf, sizeof(rbuf));
robbiew906d4682003-01-06 17:23:07 +0000138 if (bytesread < 0) {
139 tst_resm(TFAIL, "Unable to read from pipe, "
subrata_modak56207ce2009-03-23 13:35:39 +0000140 "errno=%d", errno);
robbiew906d4682003-01-06 17:23:07 +0000141 break;
142 }
subrata_modak56207ce2009-03-23 13:35:39 +0000143 switch (rbuf[1]) {
144 case 'A':
145 acnt++;
146 break;
147 case 'b':
148 bcnt++;
149 break;
150 default:
151 tst_resm(TFAIL, "Got bogus '%c' "
152 "character", rbuf[1]);
153 break;
robbiew906d4682003-01-06 17:23:07 +0000154 }
155 }
156
157 /*
158 * Try to kill the children
159 */
160 if (kill(c1pid, SIGKILL) == -1)
161 tst_resm(TFAIL, "failed to kill child 1, errno=%d",
subrata_modak56207ce2009-03-23 13:35:39 +0000162 errno);
robbiew906d4682003-01-06 17:23:07 +0000163 if (kill(c2pid, SIGKILL) == -1)
164 tst_resm(TFAIL, "failed to kill child 1, errno=%d",
subrata_modak56207ce2009-03-23 13:35:39 +0000165 errno);
robbiew906d4682003-01-06 17:23:07 +0000166
167 /*
168 * Set action for the alarm
169 */
170 if (signal(SIGALRM, alarmfunc) == SIG_ERR)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800171 tst_resm(TWARN | TERRNO, "call to signal failed");
robbiew906d4682003-01-06 17:23:07 +0000172 /*
173 * Set an alarm for 60 seconds just in case the child
174 * processes don't die
175 */
176 alarm(60);
Garrett Cooper53740502010-12-16 00:04:01 -0800177 if (waitpid(c1pid, &wtstatus, 0) != -1) {
robbiew906d4682003-01-06 17:23:07 +0000178 if (wtstatus != SIGKILL)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800179 tst_resm(TFAIL | TERRNO,
180 "unexpected wait status " "%d",
181 wtstatus);
robbiew906d4682003-01-06 17:23:07 +0000182 else
183 tst_resm(TPASS, "Child 1 killed while "
subrata_modak56207ce2009-03-23 13:35:39 +0000184 "writing to a pipe");
robbiew906d4682003-01-06 17:23:07 +0000185 }
Garrett Cooper53740502010-12-16 00:04:01 -0800186 if (waitpid(c2pid, &wtstatus, 0) != -1) {
Garrett Cooperc452c252010-12-19 10:12:42 -0800187 if (!WIFSIGNALED(wtstatus) ||
188 WTERMSIG(wtstatus) != SIGKILL)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800189 tst_resm(TFAIL | TERRNO,
190 "unexpected wait status " "%d",
191 wtstatus);
robbiew906d4682003-01-06 17:23:07 +0000192 else
193 tst_resm(TPASS, "Child 2 killed while "
subrata_modak56207ce2009-03-23 13:35:39 +0000194 "writing to a pipe");
robbiew906d4682003-01-06 17:23:07 +0000195 }
196 if (alarm(0) <= 0)
197 tst_resm(TWARN, "call to alarm(0) failed");
198 }
199 cleanup();
200
Garrett Cooper53740502010-12-16 00:04:01 -0800201 tst_exit();
robbiew906d4682003-01-06 17:23:07 +0000202}
203
204/*
205 * setup() - performs all ONE TIME setup for this test.
206 */
Mike Frysingerc57fba52014-04-09 18:56:30 -0400207void setup(void)
robbiew906d4682003-01-06 17:23:07 +0000208{
Garrett Cooper2c282152010-12-16 00:55:50 -0800209
robbiew906d4682003-01-06 17:23:07 +0000210 tst_sig(FORK, DEF_HANDLER, cleanup);
211
robbiew906d4682003-01-06 17:23:07 +0000212 TEST_PAUSE;
213}
214
215/*
216 * cleanup() - performs all ONE TIME cleanup for this test at
217 * completion or premature exit.
218 */
Mike Frysingerc57fba52014-04-09 18:56:30 -0400219void cleanup(void)
robbiew906d4682003-01-06 17:23:07 +0000220{
robbiew906d4682003-01-06 17:23:07 +0000221}
222
Mike Frysingerc57fba52014-04-09 18:56:30 -0400223void c1func(void)
robbiew906d4682003-01-06 17:23:07 +0000224{
225 if (close(fildes[0]) == -1)
subrata_modak56207ce2009-03-23 13:35:39 +0000226 tst_resm(TWARN, "Could not close fildes[0] - errno %d", errno);
227 while (1)
robbiew906d4682003-01-06 17:23:07 +0000228 if (write(fildes[1], "bbbbbbbbbbbbbbbbbbbbbbbbb", 25) == -1)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800229 tst_resm(TBROK | TERRNO, "[child 1] pipe write failed");
robbiew906d4682003-01-06 17:23:07 +0000230}
231
Mike Frysingerc57fba52014-04-09 18:56:30 -0400232void c2func(void)
robbiew906d4682003-01-06 17:23:07 +0000233{
234 if (close(fildes[0]) == -1)
subrata_modak56207ce2009-03-23 13:35:39 +0000235 tst_resm(TWARN, "Could not close fildes[0] - errno %d", errno);
236 while (1)
robbiew906d4682003-01-06 17:23:07 +0000237 if (write(fildes[1], "AAAAAAAAAAAAAAAAAAAAAAAAA", 25) == -1)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800238 tst_resm(TBROK | TERRNO, "[child 2] pipe write failed");
robbiew906d4682003-01-06 17:23:07 +0000239}
240
241void alarmfunc(int sig)
242{
243 /* for some reason tst_brkm doesn't seem to work in a signal handler */
Garrett Cooper53740502010-12-16 00:04:01 -0800244 tst_brkm(TFAIL, cleanup, "one or more children did't die in 60 second "
Wanlong Gao354ebb42012-12-07 10:10:04 +0800245 "time limit");
Garrett Cooperc452c252010-12-19 10:12:42 -0800246}