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