xref: /aosp_15_r20/external/ltp/testcases/kernel/syscalls/pipe/pipe02.c (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
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