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