xref: /freebsd/contrib/netbsd-tests/fs/fifofs/t_fifo.c (revision 57718be8fa0bd5edc11ab9a72e68cc71982939a6)
1*57718be8SEnji Cooper /* Test case written by Bharat Joshi */
2*57718be8SEnji Cooper #include <sys/cdefs.h>
3*57718be8SEnji Cooper __RCSID("$NetBSD: t_fifo.c,v 1.1 2011/12/21 00:17:07 christos Exp $");
4*57718be8SEnji Cooper 
5*57718be8SEnji Cooper #include <sys/types.h>
6*57718be8SEnji Cooper #include <sys/wait.h>
7*57718be8SEnji Cooper 
8*57718be8SEnji Cooper #include <stdio.h>
9*57718be8SEnji Cooper #include <stdlib.h>
10*57718be8SEnji Cooper #include <unistd.h>
11*57718be8SEnji Cooper #include <fcntl.h>
12*57718be8SEnji Cooper #include <errno.h>
13*57718be8SEnji Cooper #include <string.h>
14*57718be8SEnji Cooper #include <err.h>
15*57718be8SEnji Cooper #include <signal.h>
16*57718be8SEnji Cooper 
17*57718be8SEnji Cooper #ifndef STANDALONE
18*57718be8SEnji Cooper #include <atf-c.h>
19*57718be8SEnji Cooper #endif
20*57718be8SEnji Cooper 
21*57718be8SEnji Cooper #define FIFO_FILE_PATH       "./fifo_file"
22*57718be8SEnji Cooper #define NUM_MESSAGES         20
23*57718be8SEnji Cooper #define MSG_SIZE             240
24*57718be8SEnji Cooper #define MESSAGE              "I am fine"
25*57718be8SEnji Cooper 
26*57718be8SEnji Cooper static int verbose = 0;
27*57718be8SEnji Cooper 
28*57718be8SEnji Cooper /*
29*57718be8SEnji Cooper  * child_writer
30*57718be8SEnji Cooper  *
31*57718be8SEnji Cooper  * Function that runs in child context and opens and write to the FIFO.
32*57718be8SEnji Cooper  */
33*57718be8SEnji Cooper static void
34*57718be8SEnji Cooper child_writer(void)
35*57718be8SEnji Cooper {
36*57718be8SEnji Cooper 	ssize_t rv;
37*57718be8SEnji Cooper 	int fd;
38*57718be8SEnji Cooper 	size_t count;
39*57718be8SEnji Cooper 	char message[MSG_SIZE] = MESSAGE;
40*57718be8SEnji Cooper 	static const struct timespec ts = { 0, 10000 };
41*57718be8SEnji Cooper 
42*57718be8SEnji Cooper 	/* Open the fifo in write-mode */
43*57718be8SEnji Cooper 	for (;;) {
44*57718be8SEnji Cooper 		fd = open(FIFO_FILE_PATH, O_WRONLY, 0);
45*57718be8SEnji Cooper 		if (fd == -1) {
46*57718be8SEnji Cooper 			if (errno == EINTR)
47*57718be8SEnji Cooper 				continue;
48*57718be8SEnji Cooper 			err(1, "Child: can't open fifo in write mode");
49*57718be8SEnji Cooper 		}
50*57718be8SEnji Cooper 		break;
51*57718be8SEnji Cooper 	}
52*57718be8SEnji Cooper 
53*57718be8SEnji Cooper 	for (count = 0; count < NUM_MESSAGES; count++) {
54*57718be8SEnji Cooper 		rv = write(fd, message, MSG_SIZE);
55*57718be8SEnji Cooper 		if (rv == -1) {
56*57718be8SEnji Cooper 			warn("Child: Failed to write");
57*57718be8SEnji Cooper 			break;
58*57718be8SEnji Cooper 		}
59*57718be8SEnji Cooper 		if (rv != MSG_SIZE)
60*57718be8SEnji Cooper 			warnx("Child: wrote only %zd", rv);
61*57718be8SEnji Cooper 		nanosleep(&ts, NULL);
62*57718be8SEnji Cooper 	}
63*57718be8SEnji Cooper 
64*57718be8SEnji Cooper 	close(fd);
65*57718be8SEnji Cooper 	if (verbose) {
66*57718be8SEnji Cooper 		printf("Child: Closed the fifo file\n");
67*57718be8SEnji Cooper 		fflush(stdout);
68*57718be8SEnji Cooper 	}
69*57718be8SEnji Cooper }
70*57718be8SEnji Cooper 
71*57718be8SEnji Cooper /*
72*57718be8SEnji Cooper  * _sigchild_handler
73*57718be8SEnji Cooper  *
74*57718be8SEnji Cooper  * Called when a sigchild is delivered
75*57718be8SEnji Cooper  */
76*57718be8SEnji Cooper static void
77*57718be8SEnji Cooper sigchild_handler(int signo)
78*57718be8SEnji Cooper {
79*57718be8SEnji Cooper 	if (verbose) {
80*57718be8SEnji Cooper 		if (signo == SIGCHLD) {
81*57718be8SEnji Cooper 			printf("Got sigchild\n");
82*57718be8SEnji Cooper 		} else {
83*57718be8SEnji Cooper 			printf("Got %d signal\n", signo);
84*57718be8SEnji Cooper 		}
85*57718be8SEnji Cooper 		fflush(stdout);
86*57718be8SEnji Cooper 	}
87*57718be8SEnji Cooper 
88*57718be8SEnji Cooper }
89*57718be8SEnji Cooper 
90*57718be8SEnji Cooper static int
91*57718be8SEnji Cooper run(void)
92*57718be8SEnji Cooper {
93*57718be8SEnji Cooper 	pid_t pid;
94*57718be8SEnji Cooper 	ssize_t rv;
95*57718be8SEnji Cooper 	int fd, status;
96*57718be8SEnji Cooper 	size_t buf_size = MSG_SIZE;
97*57718be8SEnji Cooper 	char buf[MSG_SIZE];
98*57718be8SEnji Cooper 	struct sigaction action;
99*57718be8SEnji Cooper 	static const struct timespec ts = { 0, 500000000 };
100*57718be8SEnji Cooper 
101*57718be8SEnji Cooper 	/* Catch sigchild Signal */
102*57718be8SEnji Cooper 	memset(&action, 0, sizeof(action));
103*57718be8SEnji Cooper 	action.sa_handler = sigchild_handler;
104*57718be8SEnji Cooper 	sigemptyset(&action.sa_mask);
105*57718be8SEnji Cooper 
106*57718be8SEnji Cooper 	if (sigaction(SIGCHLD, &action, NULL) == -1)
107*57718be8SEnji Cooper 		err(1, "sigaction");
108*57718be8SEnji Cooper 
109*57718be8SEnji Cooper 	(void)unlink(FIFO_FILE_PATH);
110*57718be8SEnji Cooper 	/* First create a fifo */
111*57718be8SEnji Cooper 	if (mkfifo(FIFO_FILE_PATH, S_IRUSR | S_IWUSR) == -1)
112*57718be8SEnji Cooper 		err(1, "mkfifo");
113*57718be8SEnji Cooper 
114*57718be8SEnji Cooper 	switch ((pid = fork())) {
115*57718be8SEnji Cooper 	case -1:
116*57718be8SEnji Cooper 		err(1, "fork");
117*57718be8SEnji Cooper 	case 0:
118*57718be8SEnji Cooper 		/* Open the file in write mode so that subsequent read
119*57718be8SEnji Cooper 		 * from parent side does not block the parent..
120*57718be8SEnji Cooper 		 */
121*57718be8SEnji Cooper 		if ((fd = open(FIFO_FILE_PATH, O_WRONLY, 0)) == -1)
122*57718be8SEnji Cooper 			err(1, "failed to open fifo");
123*57718be8SEnji Cooper 
124*57718be8SEnji Cooper 		/* In child */
125*57718be8SEnji Cooper 		child_writer();
126*57718be8SEnji Cooper 		return 0;
127*57718be8SEnji Cooper 
128*57718be8SEnji Cooper 	default:
129*57718be8SEnji Cooper 		break;
130*57718be8SEnji Cooper 	}
131*57718be8SEnji Cooper 
132*57718be8SEnji Cooper 	if (verbose) {
133*57718be8SEnji Cooper 		printf("Child pid is %d\n", pid );
134*57718be8SEnji Cooper 		fflush(stdout);
135*57718be8SEnji Cooper 	}
136*57718be8SEnji Cooper 
137*57718be8SEnji Cooper 	/* In parent */
138*57718be8SEnji Cooper 	for (;;) {
139*57718be8SEnji Cooper 		if ((fd = open(FIFO_FILE_PATH, O_RDONLY, 0)) == -1) {
140*57718be8SEnji Cooper 			if (errno == EINTR)
141*57718be8SEnji Cooper 				continue;
142*57718be8SEnji Cooper 			else
143*57718be8SEnji Cooper 				err(1, "Failed to open the fifo in read mode");
144*57718be8SEnji Cooper 		}
145*57718be8SEnji Cooper 		/* Read mode is opened */
146*57718be8SEnji Cooper 		break;
147*57718be8SEnji Cooper 
148*57718be8SEnji Cooper 	}
149*57718be8SEnji Cooper 
150*57718be8SEnji Cooper 	nanosleep(&ts, NULL);
151*57718be8SEnji Cooper 	if (verbose) {
152*57718be8SEnji Cooper 		printf("Was sleeping...\n");
153*57718be8SEnji Cooper 		fflush(stdout);
154*57718be8SEnji Cooper 	}
155*57718be8SEnji Cooper 
156*57718be8SEnji Cooper 	for (;;) {
157*57718be8SEnji Cooper 		rv = read(fd, buf, buf_size);
158*57718be8SEnji Cooper 
159*57718be8SEnji Cooper 		if (rv == -1) {
160*57718be8SEnji Cooper 			warn("Failed to read");
161*57718be8SEnji Cooper 			if (errno == EINTR) {
162*57718be8SEnji Cooper 				if (verbose) {
163*57718be8SEnji Cooper 					printf("Parent interrupted, "
164*57718be8SEnji Cooper 					    "continuing...\n");
165*57718be8SEnji Cooper 					fflush(stdout);
166*57718be8SEnji Cooper 				}
167*57718be8SEnji Cooper 				continue;
168*57718be8SEnji Cooper 			}
169*57718be8SEnji Cooper 
170*57718be8SEnji Cooper 			break;
171*57718be8SEnji Cooper 		}
172*57718be8SEnji Cooper 
173*57718be8SEnji Cooper 		if (rv == 0) {
174*57718be8SEnji Cooper 			if (verbose) {
175*57718be8SEnji Cooper 				printf("Writers have closed, looks like we "
176*57718be8SEnji Cooper 				    "are done\n");
177*57718be8SEnji Cooper 				fflush(stdout);
178*57718be8SEnji Cooper 			}
179*57718be8SEnji Cooper 			break;
180*57718be8SEnji Cooper 		}
181*57718be8SEnji Cooper 
182*57718be8SEnji Cooper 		if (verbose) {
183*57718be8SEnji Cooper 			printf("Received %zd bytes message '%s'\n", rv, buf);
184*57718be8SEnji Cooper 			fflush(stdout);
185*57718be8SEnji Cooper 		}
186*57718be8SEnji Cooper 	}
187*57718be8SEnji Cooper 
188*57718be8SEnji Cooper 	close(fd);
189*57718be8SEnji Cooper 
190*57718be8SEnji Cooper 	if (verbose) {
191*57718be8SEnji Cooper 		printf("We are done.. now reap the child");
192*57718be8SEnji Cooper 		fflush(stdout);
193*57718be8SEnji Cooper 	}
194*57718be8SEnji Cooper 
195*57718be8SEnji Cooper 	// Read the child...
196*57718be8SEnji Cooper 	while (waitpid(pid, &status, 0) == -1)
197*57718be8SEnji Cooper 		if (errno != EINTR) {
198*57718be8SEnji Cooper 			warn("Failed to reap the child");
199*57718be8SEnji Cooper 			return 1;
200*57718be8SEnji Cooper 		}
201*57718be8SEnji Cooper 
202*57718be8SEnji Cooper 	if (verbose) {
203*57718be8SEnji Cooper 		printf("We are done completely\n");
204*57718be8SEnji Cooper 		fflush(stdout);
205*57718be8SEnji Cooper 	}
206*57718be8SEnji Cooper 	return 0;
207*57718be8SEnji Cooper }
208*57718be8SEnji Cooper 
209*57718be8SEnji Cooper #ifndef STANDALONE
210*57718be8SEnji Cooper ATF_TC(parent_child);
211*57718be8SEnji Cooper 
212*57718be8SEnji Cooper ATF_TC_HEAD(parent_child, tc)
213*57718be8SEnji Cooper {
214*57718be8SEnji Cooper         atf_tc_set_md_var(tc, "descr", "Checks that when a fifo is shared "
215*57718be8SEnji Cooper 	    "between a reader parent and a writer child, that read will "
216*57718be8SEnji Cooper 	    "return EOF, and not get stuck after the child exits");
217*57718be8SEnji Cooper }
218*57718be8SEnji Cooper 
219*57718be8SEnji Cooper ATF_TC_BODY(parent_child, tc)
220*57718be8SEnji Cooper {
221*57718be8SEnji Cooper         ATF_REQUIRE(run() == 0);
222*57718be8SEnji Cooper }
223*57718be8SEnji Cooper 
224*57718be8SEnji Cooper ATF_TP_ADD_TCS(tp)
225*57718be8SEnji Cooper {
226*57718be8SEnji Cooper         ATF_TP_ADD_TC(tp, parent_child);
227*57718be8SEnji Cooper 
228*57718be8SEnji Cooper         return atf_no_error();
229*57718be8SEnji Cooper }
230*57718be8SEnji Cooper #else
231*57718be8SEnji Cooper int
232*57718be8SEnji Cooper main(void)
233*57718be8SEnji Cooper {
234*57718be8SEnji Cooper 	verbose = 1;
235*57718be8SEnji Cooper 	return run();
236*57718be8SEnji Cooper }
237*57718be8SEnji Cooper #endif
238