Home | History | Annotate | Download | only in pipe
      1 /*
      2  * Copyright (c) International Business Machines  Corp., 2002
      3  *
      4  * This program is free software;  you can redistribute it and/or modify
      5  * it under the terms of the GNU General Public License as published by
      6  * the Free Software Foundation; either version 2 of the License, or
      7  * (at your option) any later version.
      8  *
      9  * This program is distributed in the hope that it will be useful,
     10  * but WITHOUT ANY WARRANTY;  without even the implied warranty of
     11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
     12  * the GNU General Public License for more details.
     13  *
     14  * You should have received a copy of the GNU General Public License
     15  * along with this program.
     16  */
     17 
     18 /*
     19  * Check that if a child has a "broken pipe", this information
     20  * is transmitted to the waiting parent.
     21  */
     22 
     23 #include <errno.h>
     24 #include <string.h>
     25 #include <unistd.h>
     26 #include <stdlib.h>
     27 #include <sys/wait.h>
     28 #include "tst_test.h"
     29 
     30 #define SIZE	5
     31 
     32 static int fd[2];
     33 static char rdbuf[SIZE];
     34 static char wrbuf[SIZE];
     35 
     36 static void do_child(void)
     37 {
     38 	SAFE_SIGNAL(SIGPIPE, SIG_DFL);
     39 	SAFE_CLOSE(fd[0]);
     40 	SAFE_WRITE(1, fd[1], wrbuf, SIZE);
     41 
     42 	TST_CHECKPOINT_WAIT(0);
     43 
     44 	SAFE_WRITE(1, fd[1], wrbuf, SIZE);
     45 	exit(0);
     46 }
     47 
     48 static void verify_pipe(void)
     49 {
     50 	int status;
     51 	int sig = 0;
     52 	pid_t pid;
     53 
     54 	memset(wrbuf, 'a', SIZE);
     55 
     56 #ifdef UCLINUX
     57 	maybe_run_child(&do_child, "dd", &fd[0], &fd[1]);
     58 #endif
     59 
     60 	TEST(pipe(fd));
     61 	if (TEST_RETURN == -1) {
     62 		tst_res(TFAIL|TERRNO, "pipe() failed");
     63 		return;
     64 	}
     65 
     66 	pid = SAFE_FORK();
     67 	if (pid == 0) {
     68 #ifdef UCLINUX
     69 		if (self_exec(av[0], "dd", fd[0], fd[1]) < 0)
     70 			tst_brk(TBROK, "self_exec failed");
     71 #else
     72 		do_child();
     73 #endif
     74 	}
     75 
     76 	memset(rdbuf, 0, SIZE);
     77 	SAFE_CLOSE(fd[1]);
     78 	SAFE_READ(1, fd[0], rdbuf, SIZE);
     79 
     80 	if (memcmp(wrbuf, rdbuf, SIZE) != 0) {
     81 		tst_res(TFAIL, "pipe read data and pipe "
     82 			"write data didn't match");
     83 		return;
     84 	}
     85 
     86 	SAFE_CLOSE(fd[0]);
     87 	TST_CHECKPOINT_WAKE(0);
     88 	SAFE_WAIT(&status);
     89 
     90 	if (!WIFSIGNALED(status)) {
     91 		tst_res(TFAIL, "Child wasn't killed by signal");
     92 	} else {
     93 		sig = WTERMSIG(status);
     94 		if (sig != SIGPIPE) {
     95 			tst_res(TFAIL, "Child killed by %s expected SIGPIPE",
     96 				tst_strsig(sig));
     97 		} else {
     98 				tst_res(TPASS, "Child killed by SIGPIPE");
     99 		}
    100 	}
    101 }
    102 
    103 static struct tst_test test = {
    104 	.forks_child = 1,
    105 	.needs_checkpoints = 1,
    106 	.test_all = verify_pipe,
    107 };
    108