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