• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
do_child(void)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 
verify_pipe(void)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 (TST_RET == -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