1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (c) International Business Machines Corp., 2002
4 */
5
6 /*
7 * Check that if a child has a "broken pipe", this information
8 * is transmitted to the waiting parent.
9 */
10
11 #include <errno.h>
12 #include <string.h>
13 #include <unistd.h>
14 #include <stdlib.h>
15 #include <sys/wait.h>
16 #include "tst_test.h"
17
18 #define SIZE 5
19
20 static int fd[2];
21 static char rdbuf[SIZE];
22 static char wrbuf[SIZE];
23
do_child(void)24 static void do_child(void)
25 {
26 SAFE_SIGNAL(SIGPIPE, SIG_DFL);
27 SAFE_CLOSE(fd[0]);
28 SAFE_WRITE(SAFE_WRITE_ALL, fd[1], wrbuf, SIZE);
29
30 TST_CHECKPOINT_WAIT(0);
31
32 SAFE_WRITE(SAFE_WRITE_ALL, fd[1], wrbuf, SIZE);
33 exit(0);
34 }
35
verify_pipe(void)36 static void verify_pipe(void)
37 {
38 int status;
39 int sig = 0;
40 pid_t pid;
41
42 memset(wrbuf, 'a', SIZE);
43
44 TEST(pipe(fd));
45 if (TST_RET == -1) {
46 tst_res(TFAIL|TTERRNO, "pipe() failed");
47 return;
48 }
49
50 pid = SAFE_FORK();
51 if (pid == 0) {
52 do_child();
53 }
54
55 memset(rdbuf, 0, SIZE);
56 SAFE_CLOSE(fd[1]);
57 SAFE_READ(1, fd[0], rdbuf, SIZE);
58
59 if (memcmp(wrbuf, rdbuf, SIZE) != 0) {
60 tst_res(TFAIL, "pipe read data and pipe "
61 "write data didn't match");
62 return;
63 }
64
65 SAFE_CLOSE(fd[0]);
66 TST_CHECKPOINT_WAKE(0);
67 SAFE_WAIT(&status);
68
69 if (!WIFSIGNALED(status)) {
70 tst_res(TFAIL, "Child wasn't killed by signal");
71 } else {
72 sig = WTERMSIG(status);
73 if (sig != SIGPIPE) {
74 tst_res(TFAIL, "Child killed by %s expected SIGPIPE",
75 tst_strsig(sig));
76 } else {
77 tst_res(TPASS, "Child killed by SIGPIPE");
78 }
79 }
80 }
81
82 static struct tst_test test = {
83 .forks_child = 1,
84 .needs_checkpoints = 1,
85 .test_all = verify_pipe,
86 };
87