1 /* 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 17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 */ 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" 52 53 char *TCID = "pipe04"; 54 int TST_TOTAL = 1; 55 56 int fildes[2]; /* fds for pipe read and write */ 57 58 void setup(void); 59 void cleanup(void); 60 void c1func(void); 61 void c2func(void); 62 void alarmfunc(int); 63 64 ssize_t do_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 75 int main(int ac, char **av) 76 { 77 int lc; 78 pid_t c1pid, c2pid; 79 int wtstatus; 80 int bytesread; 81 int acnt = 0, bcnt = 0; 82 83 char rbuf[BUFSIZ]; 84 85 tst_parse_opts(ac, av, NULL, NULL); 86 #ifdef UCLINUX 87 maybe_run_child(&c1func, "ndd", 1, &fildes[0], &fildes[1]); 88 maybe_run_child(&c2func, "ndd", 2, &fildes[0], &fildes[1]); 89 #endif 90 91 setup(); 92 93 for (lc = 0; TEST_LOOPING(lc); lc++) { 94 95 /* reset tst_count in case we are looping */ 96 tst_count = 0; 97 98 if (pipe(fildes) == -1) 99 tst_brkm(TBROK, cleanup, "pipe() failed - errno %d", 100 errno); 101 102 if ((c1pid = FORK_OR_VFORK()) == -1) 103 tst_brkm(TBROK, cleanup, "fork() failed - " 104 "errno %d", errno); 105 if (c1pid == 0) 106 #ifdef UCLINUX 107 if (self_exec(av[0], "ndd", 1, fildes[0], fildes[1]) < 108 0) { 109 tst_brkm(TBROK, cleanup, "self_exec failed"); 110 } 111 #else 112 c1func(); 113 #endif 114 if ((c2pid = FORK_OR_VFORK()) == -1) 115 tst_brkm(TBROK, cleanup, "fork() failed - " 116 "errno %d", errno); 117 if (c2pid == 0) 118 #ifdef UCLINUX 119 if (self_exec(av[0], "ndd", 2, fildes[0], fildes[1]) < 120 0) { 121 tst_brkm(TBROK, cleanup, "self_exec failed"); 122 } 123 #else 124 c2func(); 125 #endif 126 127 /* PARENT */ 128 if (close(fildes[1]) == -1) 129 tst_resm(TWARN, "Could not close fildes[1] - errno %d", 130 errno); 131 /* 132 * Read a bit from the children first 133 */ 134 while ((acnt < 100) && (bcnt < 100)) { 135 bytesread = do_read(fildes[0], rbuf, sizeof(rbuf)); 136 if (bytesread < 0) { 137 tst_resm(TFAIL, "Unable to read from pipe, " 138 "errno=%d", errno); 139 break; 140 } 141 switch (rbuf[1]) { 142 case 'A': 143 acnt++; 144 break; 145 case 'b': 146 bcnt++; 147 break; 148 default: 149 tst_resm(TFAIL, "Got bogus '%c' " 150 "character", rbuf[1]); 151 break; 152 } 153 } 154 155 /* 156 * Try to kill the children 157 */ 158 if (kill(c1pid, SIGKILL) == -1) 159 tst_resm(TFAIL, "failed to kill child 1, errno=%d", 160 errno); 161 if (kill(c2pid, SIGKILL) == -1) 162 tst_resm(TFAIL, "failed to kill child 1, errno=%d", 163 errno); 164 165 /* 166 * Set action for the alarm 167 */ 168 if (signal(SIGALRM, alarmfunc) == SIG_ERR) 169 tst_resm(TWARN | TERRNO, "call to signal failed"); 170 /* 171 * Set an alarm for 60 seconds just in case the child 172 * processes don't die 173 */ 174 alarm(60); 175 if (waitpid(c1pid, &wtstatus, 0) != -1) { 176 if (wtstatus != SIGKILL) 177 tst_resm(TFAIL | TERRNO, 178 "unexpected wait status " "%d", 179 wtstatus); 180 else 181 tst_resm(TPASS, "Child 1 killed while " 182 "writing to a pipe"); 183 } 184 if (waitpid(c2pid, &wtstatus, 0) != -1) { 185 if (!WIFSIGNALED(wtstatus) || 186 WTERMSIG(wtstatus) != SIGKILL) 187 tst_resm(TFAIL | TERRNO, 188 "unexpected wait status " "%d", 189 wtstatus); 190 else 191 tst_resm(TPASS, "Child 2 killed while " 192 "writing to a pipe"); 193 } 194 if (alarm(0) <= 0) 195 tst_resm(TWARN, "call to alarm(0) failed"); 196 } 197 cleanup(); 198 199 tst_exit(); 200 } 201 202 /* 203 * setup() - performs all ONE TIME setup for this test. 204 */ 205 void setup(void) 206 { 207 208 tst_sig(FORK, DEF_HANDLER, cleanup); 209 210 TEST_PAUSE; 211 } 212 213 /* 214 * cleanup() - performs all ONE TIME cleanup for this test at 215 * completion or premature exit. 216 */ 217 void cleanup(void) 218 { 219 } 220 221 void c1func(void) 222 { 223 if (close(fildes[0]) == -1) 224 tst_resm(TWARN, "Could not close fildes[0] - errno %d", errno); 225 while (1) 226 if (write(fildes[1], "bbbbbbbbbbbbbbbbbbbbbbbbb", 25) == -1) 227 tst_resm(TBROK | TERRNO, "[child 1] pipe write failed"); 228 } 229 230 void c2func(void) 231 { 232 if (close(fildes[0]) == -1) 233 tst_resm(TWARN, "Could not close fildes[0] - errno %d", errno); 234 while (1) 235 if (write(fildes[1], "AAAAAAAAAAAAAAAAAAAAAAAAA", 25) == -1) 236 tst_resm(TBROK | TERRNO, "[child 2] pipe write failed"); 237 } 238 239 void alarmfunc(int sig) 240 { 241 /* for some reason tst_brkm doesn't seem to work in a signal handler */ 242 tst_brkm(TFAIL, cleanup, "one or more children did't die in 60 second " 243 "time limit"); 244 } 245