1f08c3bdfSopenharmony_ci/* 2f08c3bdfSopenharmony_ci * 3f08c3bdfSopenharmony_ci * Copyright (c) International Business Machines Corp., 2002 4f08c3bdfSopenharmony_ci * 5f08c3bdfSopenharmony_ci * This program is free software; you can redistribute it and/or modify 6f08c3bdfSopenharmony_ci * it under the terms of the GNU General Public License as published by 7f08c3bdfSopenharmony_ci * the Free Software Foundation; either version 2 of the License, or 8f08c3bdfSopenharmony_ci * (at your option) any later version. 9f08c3bdfSopenharmony_ci * 10f08c3bdfSopenharmony_ci * This program is distributed in the hope that it will be useful, 11f08c3bdfSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 12f08c3bdfSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 13f08c3bdfSopenharmony_ci * the GNU General Public License for more details. 14f08c3bdfSopenharmony_ci * 15f08c3bdfSopenharmony_ci * You should have received a copy of the GNU General Public License 16f08c3bdfSopenharmony_ci * along with this program; if not, write to the Free Software 17f08c3bdfSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18f08c3bdfSopenharmony_ci */ 19f08c3bdfSopenharmony_ci 20f08c3bdfSopenharmony_ci/* 21f08c3bdfSopenharmony_ci * NAME 22f08c3bdfSopenharmony_ci * pipe04.c 23f08c3bdfSopenharmony_ci * 24f08c3bdfSopenharmony_ci * DESCRIPTION 25f08c3bdfSopenharmony_ci * Check that processes are killable, even when they are still writing 26f08c3bdfSopenharmony_ci * data to a pipe. 27f08c3bdfSopenharmony_ci * 28f08c3bdfSopenharmony_ci * ALGORITHM 29f08c3bdfSopenharmony_ci * 1. Open a pipe 30f08c3bdfSopenharmony_ci * 2. fork a two children that will write to the pipe 31f08c3bdfSopenharmony_ci * 3. read a bit from both children 32f08c3bdfSopenharmony_ci * 3. kill both children and wait to make sure they die 33f08c3bdfSopenharmony_ci * 34f08c3bdfSopenharmony_ci * USAGE: <for command-line> 35f08c3bdfSopenharmony_ci * pipe04 [-c n] [-f] [-i n] [-I x] [-P x] [-t] 36f08c3bdfSopenharmony_ci * where, -c n : Run n copies concurrently. 37f08c3bdfSopenharmony_ci * -f : Turn off functionality Testing. 38f08c3bdfSopenharmony_ci * -i n : Execute test n times. 39f08c3bdfSopenharmony_ci * -I x : Execute test for x seconds. 40f08c3bdfSopenharmony_ci * -P x : Pause for x seconds between iterations. 41f08c3bdfSopenharmony_ci * -t : Turn on syscall timing. 42f08c3bdfSopenharmony_ci * 43f08c3bdfSopenharmony_ci * HISTORY 44f08c3bdfSopenharmony_ci * 11/2002 Ported by Paul Larson 45f08c3bdfSopenharmony_ci */ 46f08c3bdfSopenharmony_ci#include <unistd.h> 47f08c3bdfSopenharmony_ci#include <errno.h> 48f08c3bdfSopenharmony_ci#include <signal.h> 49f08c3bdfSopenharmony_ci#include <sys/types.h> 50f08c3bdfSopenharmony_ci#include <sys/wait.h> 51f08c3bdfSopenharmony_ci#include "test.h" 52f08c3bdfSopenharmony_ci#include "safe_macros.h" 53f08c3bdfSopenharmony_ci 54f08c3bdfSopenharmony_cichar *TCID = "pipe04"; 55f08c3bdfSopenharmony_ciint TST_TOTAL = 1; 56f08c3bdfSopenharmony_ci 57f08c3bdfSopenharmony_ciint fildes[2]; /* fds for pipe read and write */ 58f08c3bdfSopenharmony_ci 59f08c3bdfSopenharmony_civoid setup(void); 60f08c3bdfSopenharmony_civoid cleanup(void); 61f08c3bdfSopenharmony_civoid c1func(void); 62f08c3bdfSopenharmony_civoid c2func(void); 63f08c3bdfSopenharmony_civoid alarmfunc(int); 64f08c3bdfSopenharmony_ci 65f08c3bdfSopenharmony_cissize_t do_read(int fd, void *buf, size_t count) 66f08c3bdfSopenharmony_ci{ 67f08c3bdfSopenharmony_ci ssize_t n; 68f08c3bdfSopenharmony_ci 69f08c3bdfSopenharmony_ci do { 70f08c3bdfSopenharmony_ci n = read(fd, buf, count); 71f08c3bdfSopenharmony_ci } while (n < 0 && errno == EINTR); 72f08c3bdfSopenharmony_ci 73f08c3bdfSopenharmony_ci return n; 74f08c3bdfSopenharmony_ci} 75f08c3bdfSopenharmony_ci 76f08c3bdfSopenharmony_ciint main(int ac, char **av) 77f08c3bdfSopenharmony_ci{ 78f08c3bdfSopenharmony_ci int lc; 79f08c3bdfSopenharmony_ci pid_t c1pid, c2pid; 80f08c3bdfSopenharmony_ci int wtstatus; 81f08c3bdfSopenharmony_ci int bytesread; 82f08c3bdfSopenharmony_ci int acnt = 0, bcnt = 0; 83f08c3bdfSopenharmony_ci 84f08c3bdfSopenharmony_ci char rbuf[BUFSIZ]; 85f08c3bdfSopenharmony_ci 86f08c3bdfSopenharmony_ci tst_parse_opts(ac, av, NULL, NULL); 87f08c3bdfSopenharmony_ci#ifdef UCLINUX 88f08c3bdfSopenharmony_ci maybe_run_child(&c1func, "ndd", 1, &fildes[0], &fildes[1]); 89f08c3bdfSopenharmony_ci maybe_run_child(&c2func, "ndd", 2, &fildes[0], &fildes[1]); 90f08c3bdfSopenharmony_ci#endif 91f08c3bdfSopenharmony_ci 92f08c3bdfSopenharmony_ci setup(); 93f08c3bdfSopenharmony_ci 94f08c3bdfSopenharmony_ci for (lc = 0; TEST_LOOPING(lc); lc++) { 95f08c3bdfSopenharmony_ci 96f08c3bdfSopenharmony_ci /* reset tst_count in case we are looping */ 97f08c3bdfSopenharmony_ci tst_count = 0; 98f08c3bdfSopenharmony_ci 99f08c3bdfSopenharmony_ci SAFE_PIPE(cleanup, fildes); 100f08c3bdfSopenharmony_ci 101f08c3bdfSopenharmony_ci if ((c1pid = FORK_OR_VFORK()) == -1) 102f08c3bdfSopenharmony_ci tst_brkm(TBROK, cleanup, "fork() failed - " 103f08c3bdfSopenharmony_ci "errno %d", errno); 104f08c3bdfSopenharmony_ci if (c1pid == 0) 105f08c3bdfSopenharmony_ci#ifdef UCLINUX 106f08c3bdfSopenharmony_ci if (self_exec(av[0], "ndd", 1, fildes[0], fildes[1]) < 107f08c3bdfSopenharmony_ci 0) { 108f08c3bdfSopenharmony_ci tst_brkm(TBROK, cleanup, "self_exec failed"); 109f08c3bdfSopenharmony_ci } 110f08c3bdfSopenharmony_ci#else 111f08c3bdfSopenharmony_ci c1func(); 112f08c3bdfSopenharmony_ci#endif 113f08c3bdfSopenharmony_ci if ((c2pid = FORK_OR_VFORK()) == -1) 114f08c3bdfSopenharmony_ci tst_brkm(TBROK, cleanup, "fork() failed - " 115f08c3bdfSopenharmony_ci "errno %d", errno); 116f08c3bdfSopenharmony_ci if (c2pid == 0) 117f08c3bdfSopenharmony_ci#ifdef UCLINUX 118f08c3bdfSopenharmony_ci if (self_exec(av[0], "ndd", 2, fildes[0], fildes[1]) < 119f08c3bdfSopenharmony_ci 0) { 120f08c3bdfSopenharmony_ci tst_brkm(TBROK, cleanup, "self_exec failed"); 121f08c3bdfSopenharmony_ci } 122f08c3bdfSopenharmony_ci#else 123f08c3bdfSopenharmony_ci c2func(); 124f08c3bdfSopenharmony_ci#endif 125f08c3bdfSopenharmony_ci 126f08c3bdfSopenharmony_ci /* PARENT */ 127f08c3bdfSopenharmony_ci if (close(fildes[1]) == -1) 128f08c3bdfSopenharmony_ci tst_resm(TWARN, "Could not close fildes[1] - errno %d", 129f08c3bdfSopenharmony_ci errno); 130f08c3bdfSopenharmony_ci /* 131f08c3bdfSopenharmony_ci * Read a bit from the children first 132f08c3bdfSopenharmony_ci */ 133f08c3bdfSopenharmony_ci while ((acnt < 100) && (bcnt < 100)) { 134f08c3bdfSopenharmony_ci bytesread = do_read(fildes[0], rbuf, sizeof(rbuf)); 135f08c3bdfSopenharmony_ci if (bytesread < 0) { 136f08c3bdfSopenharmony_ci tst_resm(TFAIL, "Unable to read from pipe, " 137f08c3bdfSopenharmony_ci "errno=%d", errno); 138f08c3bdfSopenharmony_ci break; 139f08c3bdfSopenharmony_ci } 140f08c3bdfSopenharmony_ci switch (rbuf[1]) { 141f08c3bdfSopenharmony_ci case 'A': 142f08c3bdfSopenharmony_ci acnt++; 143f08c3bdfSopenharmony_ci break; 144f08c3bdfSopenharmony_ci case 'b': 145f08c3bdfSopenharmony_ci bcnt++; 146f08c3bdfSopenharmony_ci break; 147f08c3bdfSopenharmony_ci default: 148f08c3bdfSopenharmony_ci tst_resm(TFAIL, "Got bogus '%c' " 149f08c3bdfSopenharmony_ci "character", rbuf[1]); 150f08c3bdfSopenharmony_ci break; 151f08c3bdfSopenharmony_ci } 152f08c3bdfSopenharmony_ci } 153f08c3bdfSopenharmony_ci 154f08c3bdfSopenharmony_ci /* 155f08c3bdfSopenharmony_ci * Try to kill the children 156f08c3bdfSopenharmony_ci */ 157f08c3bdfSopenharmony_ci if (kill(c1pid, SIGKILL) == -1) 158f08c3bdfSopenharmony_ci tst_resm(TFAIL, "failed to kill child 1, errno=%d", 159f08c3bdfSopenharmony_ci errno); 160f08c3bdfSopenharmony_ci if (kill(c2pid, SIGKILL) == -1) 161f08c3bdfSopenharmony_ci tst_resm(TFAIL, "failed to kill child 1, errno=%d", 162f08c3bdfSopenharmony_ci errno); 163f08c3bdfSopenharmony_ci 164f08c3bdfSopenharmony_ci /* 165f08c3bdfSopenharmony_ci * Set action for the alarm 166f08c3bdfSopenharmony_ci */ 167f08c3bdfSopenharmony_ci if (signal(SIGALRM, alarmfunc) == SIG_ERR) 168f08c3bdfSopenharmony_ci tst_resm(TWARN | TERRNO, "call to signal failed"); 169f08c3bdfSopenharmony_ci /* 170f08c3bdfSopenharmony_ci * Set an alarm for 60 seconds just in case the child 171f08c3bdfSopenharmony_ci * processes don't die 172f08c3bdfSopenharmony_ci */ 173f08c3bdfSopenharmony_ci alarm(60); 174f08c3bdfSopenharmony_ci if (waitpid(c1pid, &wtstatus, 0) != -1) { 175f08c3bdfSopenharmony_ci if (wtstatus != SIGKILL) 176f08c3bdfSopenharmony_ci tst_resm(TFAIL | TERRNO, 177f08c3bdfSopenharmony_ci "unexpected wait status " "%d", 178f08c3bdfSopenharmony_ci wtstatus); 179f08c3bdfSopenharmony_ci else 180f08c3bdfSopenharmony_ci tst_resm(TPASS, "Child 1 killed while " 181f08c3bdfSopenharmony_ci "writing to a pipe"); 182f08c3bdfSopenharmony_ci } 183f08c3bdfSopenharmony_ci if (waitpid(c2pid, &wtstatus, 0) != -1) { 184f08c3bdfSopenharmony_ci if (!WIFSIGNALED(wtstatus) || 185f08c3bdfSopenharmony_ci WTERMSIG(wtstatus) != SIGKILL) 186f08c3bdfSopenharmony_ci tst_resm(TFAIL | TERRNO, 187f08c3bdfSopenharmony_ci "unexpected wait status " "%d", 188f08c3bdfSopenharmony_ci wtstatus); 189f08c3bdfSopenharmony_ci else 190f08c3bdfSopenharmony_ci tst_resm(TPASS, "Child 2 killed while " 191f08c3bdfSopenharmony_ci "writing to a pipe"); 192f08c3bdfSopenharmony_ci } 193f08c3bdfSopenharmony_ci if (alarm(0) <= 0) 194f08c3bdfSopenharmony_ci tst_resm(TWARN, "call to alarm(0) failed"); 195f08c3bdfSopenharmony_ci } 196f08c3bdfSopenharmony_ci cleanup(); 197f08c3bdfSopenharmony_ci 198f08c3bdfSopenharmony_ci tst_exit(); 199f08c3bdfSopenharmony_ci} 200f08c3bdfSopenharmony_ci 201f08c3bdfSopenharmony_ci/* 202f08c3bdfSopenharmony_ci * setup() - performs all ONE TIME setup for this test. 203f08c3bdfSopenharmony_ci */ 204f08c3bdfSopenharmony_civoid setup(void) 205f08c3bdfSopenharmony_ci{ 206f08c3bdfSopenharmony_ci 207f08c3bdfSopenharmony_ci tst_sig(FORK, DEF_HANDLER, cleanup); 208f08c3bdfSopenharmony_ci 209f08c3bdfSopenharmony_ci TEST_PAUSE; 210f08c3bdfSopenharmony_ci} 211f08c3bdfSopenharmony_ci 212f08c3bdfSopenharmony_ci/* 213f08c3bdfSopenharmony_ci * cleanup() - performs all ONE TIME cleanup for this test at 214f08c3bdfSopenharmony_ci * completion or premature exit. 215f08c3bdfSopenharmony_ci */ 216f08c3bdfSopenharmony_civoid cleanup(void) 217f08c3bdfSopenharmony_ci{ 218f08c3bdfSopenharmony_ci} 219f08c3bdfSopenharmony_ci 220f08c3bdfSopenharmony_civoid c1func(void) 221f08c3bdfSopenharmony_ci{ 222f08c3bdfSopenharmony_ci if (close(fildes[0]) == -1) 223f08c3bdfSopenharmony_ci tst_resm(TWARN, "Could not close fildes[0] - errno %d", errno); 224f08c3bdfSopenharmony_ci while (1) 225f08c3bdfSopenharmony_ci if (write(fildes[1], "bbbbbbbbbbbbbbbbbbbbbbbbb", 25) == -1) 226f08c3bdfSopenharmony_ci tst_resm(TBROK | TERRNO, "[child 1] pipe write failed"); 227f08c3bdfSopenharmony_ci} 228f08c3bdfSopenharmony_ci 229f08c3bdfSopenharmony_civoid c2func(void) 230f08c3bdfSopenharmony_ci{ 231f08c3bdfSopenharmony_ci if (close(fildes[0]) == -1) 232f08c3bdfSopenharmony_ci tst_resm(TWARN, "Could not close fildes[0] - errno %d", errno); 233f08c3bdfSopenharmony_ci while (1) 234f08c3bdfSopenharmony_ci if (write(fildes[1], "AAAAAAAAAAAAAAAAAAAAAAAAA", 25) == -1) 235f08c3bdfSopenharmony_ci tst_resm(TBROK | TERRNO, "[child 2] pipe write failed"); 236f08c3bdfSopenharmony_ci} 237f08c3bdfSopenharmony_ci 238f08c3bdfSopenharmony_civoid alarmfunc(int sig LTP_ATTRIBUTE_UNUSED) 239f08c3bdfSopenharmony_ci{ 240f08c3bdfSopenharmony_ci /* for some reason tst_brkm doesn't seem to work in a signal handler */ 241f08c3bdfSopenharmony_ci tst_brkm(TFAIL, cleanup, "one or more children did't die in 60 second " 242f08c3bdfSopenharmony_ci "time limit"); 243f08c3bdfSopenharmony_ci} 244