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