1*3cedbec3SEnji Cooper /*-
2*3cedbec3SEnji Cooper * Copyright (c) 2005 Robert N. M. Watson
3*3cedbec3SEnji Cooper * All rights reserved.
4*3cedbec3SEnji Cooper *
5*3cedbec3SEnji Cooper * Redistribution and use in source and binary forms, with or without
6*3cedbec3SEnji Cooper * modification, are permitted provided that the following conditions
7*3cedbec3SEnji Cooper * are met:
8*3cedbec3SEnji Cooper * 1. Redistributions of source code must retain the above copyright
9*3cedbec3SEnji Cooper * notice, this list of conditions and the following disclaimer.
10*3cedbec3SEnji Cooper * 2. Redistributions in binary form must reproduce the above copyright
11*3cedbec3SEnji Cooper * notice, this list of conditions and the following disclaimer in the
12*3cedbec3SEnji Cooper * documentation and/or other materials provided with the distribution.
13*3cedbec3SEnji Cooper *
14*3cedbec3SEnji Cooper * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15*3cedbec3SEnji Cooper * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16*3cedbec3SEnji Cooper * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17*3cedbec3SEnji Cooper * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18*3cedbec3SEnji Cooper * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19*3cedbec3SEnji Cooper * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20*3cedbec3SEnji Cooper * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21*3cedbec3SEnji Cooper * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22*3cedbec3SEnji Cooper * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23*3cedbec3SEnji Cooper * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24*3cedbec3SEnji Cooper * SUCH DAMAGE.
25*3cedbec3SEnji Cooper */
26*3cedbec3SEnji Cooper
27*3cedbec3SEnji Cooper #include <sys/types.h>
28*3cedbec3SEnji Cooper #include <sys/stat.h>
29*3cedbec3SEnji Cooper #include <sys/wait.h>
30*3cedbec3SEnji Cooper
31*3cedbec3SEnji Cooper #include <err.h>
32*3cedbec3SEnji Cooper #include <errno.h>
33*3cedbec3SEnji Cooper #include <fcntl.h>
34*3cedbec3SEnji Cooper #include <limits.h>
35*3cedbec3SEnji Cooper #include <signal.h>
36*3cedbec3SEnji Cooper #include <stdio.h>
37*3cedbec3SEnji Cooper #include <stdlib.h>
38*3cedbec3SEnji Cooper #include <string.h>
39*3cedbec3SEnji Cooper #include <unistd.h>
40*3cedbec3SEnji Cooper
41*3cedbec3SEnji Cooper /*
42*3cedbec3SEnji Cooper * Regression test to exercise various POSIX-defined parts of fifo behavior
43*3cedbec3SEnji Cooper * described for open(2):
44*3cedbec3SEnji Cooper *
45*3cedbec3SEnji Cooper * O_NONBLOCK
46*3cedbec3SEnji Cooper * When opening a FIFO with O_RDONLY or O_WRONLY set:
47*3cedbec3SEnji Cooper *
48*3cedbec3SEnji Cooper * - If O_NONBLOCK is set, an open() for reading-only shall return without
49*3cedbec3SEnji Cooper * delay. An open() for writing-only shall return an error if no process
50*3cedbec3SEnji Cooper * currently has the file open for reading.
51*3cedbec3SEnji Cooper *
52*3cedbec3SEnji Cooper * - If O_NONBLOCK is clear, an open() for reading-only shall block the
53*3cedbec3SEnji Cooper * calling thread until a thread opens the file for writing. An open()
54*3cedbec3SEnji Cooper * for writing-only shall block the calling thread until a thread opens
55*3cedbec3SEnji Cooper * the file for reading.
56*3cedbec3SEnji Cooper *
57*3cedbec3SEnji Cooper * When opening a block special or character special file that supports
58*3cedbec3SEnji Cooper * non-blocking opens:
59*3cedbec3SEnji Cooper *
60*3cedbec3SEnji Cooper * - If O_NONBLOCK is set, the open() function shall return without blocking
61*3cedbec3SEnji Cooper * for the device to be ready or available. Subsequent behavior of the
62*3cedbec3SEnji Cooper * device is device-specific.
63*3cedbec3SEnji Cooper *
64*3cedbec3SEnji Cooper * - If O_NONBLOCK is clear, the open() function shall block the calling
65*3cedbec3SEnji Cooper * thread until the device is ready or available before returning.
66*3cedbec3SEnji Cooper *
67*3cedbec3SEnji Cooper * Special errors:
68*3cedbec3SEnji Cooper *
69*3cedbec3SEnji Cooper * [ENXIO]
70*3cedbec3SEnji Cooper * O_NONBLOCK is set, the named file is a FIFO, O_WRONLY is set, and no
71*3cedbec3SEnji Cooper * process has the file open for reading.
72*3cedbec3SEnji Cooper */
73*3cedbec3SEnji Cooper
74*3cedbec3SEnji Cooper /*
75*3cedbec3SEnji Cooper * In order to test blocking/non-blocking behavior, test processes must
76*3cedbec3SEnji Cooper * potentially block themselves until released. As bugs in blocking result
77*3cedbec3SEnji Cooper * in processes that won't un-block, we must sacrifice a process to the task,
78*3cedbec3SEnji Cooper * watching and potentially killing it after a time-out. The main test
79*3cedbec3SEnji Cooper * process is never used to open or act directly on a fifo (other than to
80*3cedbec3SEnji Cooper * create or unlink it) in order to avoid the main test process being
81*3cedbec3SEnji Cooper * blocked.
82*3cedbec3SEnji Cooper */
83*3cedbec3SEnji Cooper
84*3cedbec3SEnji Cooper /*
85*3cedbec3SEnji Cooper * All activity occurs within a temporary directory created early in the
86*3cedbec3SEnji Cooper * test.
87*3cedbec3SEnji Cooper */
88*3cedbec3SEnji Cooper static char temp_dir[PATH_MAX];
89*3cedbec3SEnji Cooper
90*3cedbec3SEnji Cooper static void __unused
atexit_temp_dir(void)91*3cedbec3SEnji Cooper atexit_temp_dir(void)
92*3cedbec3SEnji Cooper {
93*3cedbec3SEnji Cooper
94*3cedbec3SEnji Cooper rmdir(temp_dir);
95*3cedbec3SEnji Cooper }
96*3cedbec3SEnji Cooper
97*3cedbec3SEnji Cooper /*
98*3cedbec3SEnji Cooper * Run a function in a particular test process.
99*3cedbec3SEnji Cooper */
100*3cedbec3SEnji Cooper static int
run_in_process(int (* func)(void),pid_t * pidp,const char * errstr)101*3cedbec3SEnji Cooper run_in_process(int (*func)(void), pid_t *pidp, const char *errstr)
102*3cedbec3SEnji Cooper {
103*3cedbec3SEnji Cooper pid_t pid;
104*3cedbec3SEnji Cooper
105*3cedbec3SEnji Cooper pid = fork();
106*3cedbec3SEnji Cooper if (pid < 0) {
107*3cedbec3SEnji Cooper warn("%s: run_in_process: fork", errstr);
108*3cedbec3SEnji Cooper return (-1);
109*3cedbec3SEnji Cooper }
110*3cedbec3SEnji Cooper
111*3cedbec3SEnji Cooper if (pid == 0)
112*3cedbec3SEnji Cooper exit(func());
113*3cedbec3SEnji Cooper
114*3cedbec3SEnji Cooper if (pidp != NULL)
115*3cedbec3SEnji Cooper *pidp = pid;
116*3cedbec3SEnji Cooper
117*3cedbec3SEnji Cooper return (0);
118*3cedbec3SEnji Cooper }
119*3cedbec3SEnji Cooper
120*3cedbec3SEnji Cooper /*
121*3cedbec3SEnji Cooper * Wait for a process on a timeout, and if the timeout expires, kill the
122*3cedbec3SEnji Cooper * process. Test each second rather than waiting the full timeout at once to
123*3cedbec3SEnji Cooper * minimize the amount of time spent hanging around unnecessarily.
124*3cedbec3SEnji Cooper */
125*3cedbec3SEnji Cooper static int
wait_and_timeout(pid_t pid,int timeout,int * status,const char * errstr)126*3cedbec3SEnji Cooper wait_and_timeout(pid_t pid, int timeout, int *status, const char *errstr)
127*3cedbec3SEnji Cooper {
128*3cedbec3SEnji Cooper pid_t wpid;
129*3cedbec3SEnji Cooper int i;
130*3cedbec3SEnji Cooper
131*3cedbec3SEnji Cooper /*
132*3cedbec3SEnji Cooper * Count up to the timeout, but do a non-hanging waitpid() after each
133*3cedbec3SEnji Cooper * second so we can avoid waiting a lot of extra time.
134*3cedbec3SEnji Cooper */
135*3cedbec3SEnji Cooper for (i = 0; i < timeout; i++) {
136*3cedbec3SEnji Cooper wpid = waitpid(pid, status, WNOHANG);
137*3cedbec3SEnji Cooper if (wpid < 0) {
138*3cedbec3SEnji Cooper warn("%s: wait_and_timeout: waitpid %d", errstr, pid);
139*3cedbec3SEnji Cooper return (-1);
140*3cedbec3SEnji Cooper }
141*3cedbec3SEnji Cooper
142*3cedbec3SEnji Cooper if (wpid == pid)
143*3cedbec3SEnji Cooper return (0);
144*3cedbec3SEnji Cooper
145*3cedbec3SEnji Cooper sleep(1);
146*3cedbec3SEnji Cooper }
147*3cedbec3SEnji Cooper
148*3cedbec3SEnji Cooper wpid = waitpid(pid, status, WNOHANG);
149*3cedbec3SEnji Cooper if (wpid < 0) {
150*3cedbec3SEnji Cooper warn("%s: wait_and_timeout: waitpid %d", errstr, pid);
151*3cedbec3SEnji Cooper return (-1);
152*3cedbec3SEnji Cooper }
153*3cedbec3SEnji Cooper
154*3cedbec3SEnji Cooper if (wpid == pid)
155*3cedbec3SEnji Cooper return (0);
156*3cedbec3SEnji Cooper
157*3cedbec3SEnji Cooper if (kill(pid, SIGTERM) < 0) {
158*3cedbec3SEnji Cooper warn("%s: wait_and_timeout: kill %d", errstr, pid);
159*3cedbec3SEnji Cooper return (-1);
160*3cedbec3SEnji Cooper }
161*3cedbec3SEnji Cooper
162*3cedbec3SEnji Cooper wpid = waitpid(pid, status, 0);
163*3cedbec3SEnji Cooper if (wpid < 0) {
164*3cedbec3SEnji Cooper warn("%s: wait_and_timeout: waitpid %d", errstr, pid);
165*3cedbec3SEnji Cooper return (-1);
166*3cedbec3SEnji Cooper }
167*3cedbec3SEnji Cooper
168*3cedbec3SEnji Cooper if (wpid != pid) {
169*3cedbec3SEnji Cooper warn("%s: waitpid: returned %d not %d", errstr, wpid, pid);
170*3cedbec3SEnji Cooper return (-1);
171*3cedbec3SEnji Cooper }
172*3cedbec3SEnji Cooper
173*3cedbec3SEnji Cooper warnx("%s: process blocked", errstr);
174*3cedbec3SEnji Cooper return (-1);
175*3cedbec3SEnji Cooper }
176*3cedbec3SEnji Cooper
177*3cedbec3SEnji Cooper static int
non_blocking_open_reader(void)178*3cedbec3SEnji Cooper non_blocking_open_reader(void)
179*3cedbec3SEnji Cooper {
180*3cedbec3SEnji Cooper int fd;
181*3cedbec3SEnji Cooper
182*3cedbec3SEnji Cooper fd = open("testfifo", O_RDONLY | O_NONBLOCK);
183*3cedbec3SEnji Cooper if (fd < 0)
184*3cedbec3SEnji Cooper return (errno);
185*3cedbec3SEnji Cooper close(fd);
186*3cedbec3SEnji Cooper
187*3cedbec3SEnji Cooper return (0);
188*3cedbec3SEnji Cooper }
189*3cedbec3SEnji Cooper
190*3cedbec3SEnji Cooper static int
non_blocking_open_writer(void)191*3cedbec3SEnji Cooper non_blocking_open_writer(void)
192*3cedbec3SEnji Cooper {
193*3cedbec3SEnji Cooper int fd;
194*3cedbec3SEnji Cooper
195*3cedbec3SEnji Cooper fd = open("testfifo", O_WRONLY | O_NONBLOCK);
196*3cedbec3SEnji Cooper if (fd < 0)
197*3cedbec3SEnji Cooper return (errno);
198*3cedbec3SEnji Cooper close(fd);
199*3cedbec3SEnji Cooper
200*3cedbec3SEnji Cooper return (0);
201*3cedbec3SEnji Cooper }
202*3cedbec3SEnji Cooper
203*3cedbec3SEnji Cooper static int
blocking_open_reader(void)204*3cedbec3SEnji Cooper blocking_open_reader(void)
205*3cedbec3SEnji Cooper {
206*3cedbec3SEnji Cooper int fd;
207*3cedbec3SEnji Cooper
208*3cedbec3SEnji Cooper fd = open("testfifo", O_RDONLY);
209*3cedbec3SEnji Cooper if (fd < 0)
210*3cedbec3SEnji Cooper return (errno);
211*3cedbec3SEnji Cooper close(fd);
212*3cedbec3SEnji Cooper
213*3cedbec3SEnji Cooper return (0);
214*3cedbec3SEnji Cooper }
215*3cedbec3SEnji Cooper
216*3cedbec3SEnji Cooper static int
blocking_open_writer(void)217*3cedbec3SEnji Cooper blocking_open_writer(void)
218*3cedbec3SEnji Cooper {
219*3cedbec3SEnji Cooper int fd;
220*3cedbec3SEnji Cooper
221*3cedbec3SEnji Cooper fd = open("testfifo", O_WRONLY);
222*3cedbec3SEnji Cooper if (fd < 0)
223*3cedbec3SEnji Cooper return (errno);
224*3cedbec3SEnji Cooper close(fd);
225*3cedbec3SEnji Cooper
226*3cedbec3SEnji Cooper return (0);
227*3cedbec3SEnji Cooper }
228*3cedbec3SEnji Cooper
229*3cedbec3SEnji Cooper static void
test_blocking_reader(void)230*3cedbec3SEnji Cooper test_blocking_reader(void)
231*3cedbec3SEnji Cooper {
232*3cedbec3SEnji Cooper pid_t reader_pid, writer_pid, wpid;
233*3cedbec3SEnji Cooper int error, status;
234*3cedbec3SEnji Cooper
235*3cedbec3SEnji Cooper if (mkfifo("testfifo", 0600) < 0)
236*3cedbec3SEnji Cooper err(-1, "test_blocking_reader: mkfifo: testfifo");
237*3cedbec3SEnji Cooper
238*3cedbec3SEnji Cooper /*
239*3cedbec3SEnji Cooper * Block a process in opening the fifo.
240*3cedbec3SEnji Cooper */
241*3cedbec3SEnji Cooper if (run_in_process(blocking_open_reader, &reader_pid,
242*3cedbec3SEnji Cooper "test_blocking_reader: blocking_open_reader") < 0) {
243*3cedbec3SEnji Cooper (void)unlink("testfifo");
244*3cedbec3SEnji Cooper exit(-1);
245*3cedbec3SEnji Cooper }
246*3cedbec3SEnji Cooper
247*3cedbec3SEnji Cooper /*
248*3cedbec3SEnji Cooper * Test that it blocked.
249*3cedbec3SEnji Cooper */
250*3cedbec3SEnji Cooper sleep(5);
251*3cedbec3SEnji Cooper wpid = waitpid(reader_pid, &status, WNOHANG);
252*3cedbec3SEnji Cooper if (wpid < 0) {
253*3cedbec3SEnji Cooper error = errno;
254*3cedbec3SEnji Cooper (void)unlink("testfifo");
255*3cedbec3SEnji Cooper errno = error;
256*3cedbec3SEnji Cooper err(-1, "test_blocking_reader: waitpid %d", reader_pid);
257*3cedbec3SEnji Cooper }
258*3cedbec3SEnji Cooper
259*3cedbec3SEnji Cooper if (wpid != 0 && wpid != reader_pid) {
260*3cedbec3SEnji Cooper (void)unlink("testfifo");
261*3cedbec3SEnji Cooper errx(-1, "test_blocking_reader: waitpid %d returned %d",
262*3cedbec3SEnji Cooper reader_pid, wpid);
263*3cedbec3SEnji Cooper }
264*3cedbec3SEnji Cooper
265*3cedbec3SEnji Cooper if (wpid == reader_pid) {
266*3cedbec3SEnji Cooper (void)unlink("testfifo");
267*3cedbec3SEnji Cooper errx(-1, "test_blocking_reader: blocking child didn't "
268*3cedbec3SEnji Cooper "block");
269*3cedbec3SEnji Cooper }
270*3cedbec3SEnji Cooper
271*3cedbec3SEnji Cooper /*
272*3cedbec3SEnji Cooper * Unblock the blocking reader.
273*3cedbec3SEnji Cooper */
274*3cedbec3SEnji Cooper if (run_in_process(blocking_open_writer, &writer_pid,
275*3cedbec3SEnji Cooper "test_blocking_reader: blocking_open_writer") < 0) {
276*3cedbec3SEnji Cooper (void)unlink("testfifo");
277*3cedbec3SEnji Cooper (void)kill(reader_pid, SIGTERM);
278*3cedbec3SEnji Cooper (void)waitpid(reader_pid, &status, 0);
279*3cedbec3SEnji Cooper exit(-1);
280*3cedbec3SEnji Cooper }
281*3cedbec3SEnji Cooper
282*3cedbec3SEnji Cooper /*
283*3cedbec3SEnji Cooper * Make sure both processes exited quickly (<1 second) to make sure
284*3cedbec3SEnji Cooper * they didn't block, and GC.
285*3cedbec3SEnji Cooper */
286*3cedbec3SEnji Cooper if (wait_and_timeout(reader_pid, 1, &status,
287*3cedbec3SEnji Cooper "test_blocking_reader: blocking_open_reader") < 0) {
288*3cedbec3SEnji Cooper (void)unlink("testinfo");
289*3cedbec3SEnji Cooper (void)kill(reader_pid, SIGTERM);
290*3cedbec3SEnji Cooper (void)kill(writer_pid, SIGTERM);
291*3cedbec3SEnji Cooper exit(-1);
292*3cedbec3SEnji Cooper }
293*3cedbec3SEnji Cooper
294*3cedbec3SEnji Cooper if (wait_and_timeout(writer_pid, 1, &status,
295*3cedbec3SEnji Cooper "test_blocking_reader: blocking_open_writer") < 0) {
296*3cedbec3SEnji Cooper (void)unlink("testinfo");
297*3cedbec3SEnji Cooper (void)kill(writer_pid, SIGTERM);
298*3cedbec3SEnji Cooper exit(-1);
299*3cedbec3SEnji Cooper }
300*3cedbec3SEnji Cooper
301*3cedbec3SEnji Cooper if (unlink("testfifo") < 0)
302*3cedbec3SEnji Cooper err(-1, "test_blocking_reader: unlink: testfifo");
303*3cedbec3SEnji Cooper }
304*3cedbec3SEnji Cooper static void
test_blocking_writer(void)305*3cedbec3SEnji Cooper test_blocking_writer(void)
306*3cedbec3SEnji Cooper {
307*3cedbec3SEnji Cooper pid_t reader_pid, writer_pid, wpid;
308*3cedbec3SEnji Cooper int error, status;
309*3cedbec3SEnji Cooper
310*3cedbec3SEnji Cooper if (mkfifo("testfifo", 0600) < 0)
311*3cedbec3SEnji Cooper err(-1, "test_blocking_writer: mkfifo: testfifo");
312*3cedbec3SEnji Cooper
313*3cedbec3SEnji Cooper /*
314*3cedbec3SEnji Cooper * Block a process in opening the fifo.
315*3cedbec3SEnji Cooper */
316*3cedbec3SEnji Cooper if (run_in_process(blocking_open_writer, &writer_pid,
317*3cedbec3SEnji Cooper "test_blocking_writer: blocking_open_writer") < 0) {
318*3cedbec3SEnji Cooper (void)unlink("testfifo");
319*3cedbec3SEnji Cooper exit(-1);
320*3cedbec3SEnji Cooper }
321*3cedbec3SEnji Cooper
322*3cedbec3SEnji Cooper /*
323*3cedbec3SEnji Cooper * Test that it blocked.
324*3cedbec3SEnji Cooper */
325*3cedbec3SEnji Cooper sleep(5);
326*3cedbec3SEnji Cooper wpid = waitpid(writer_pid, &status, WNOHANG);
327*3cedbec3SEnji Cooper if (wpid < 0) {
328*3cedbec3SEnji Cooper error = errno;
329*3cedbec3SEnji Cooper (void)unlink("testfifo");
330*3cedbec3SEnji Cooper errno = error;
331*3cedbec3SEnji Cooper err(-1, "test_blocking_writer: waitpid %d", writer_pid);
332*3cedbec3SEnji Cooper }
333*3cedbec3SEnji Cooper
334*3cedbec3SEnji Cooper if (wpid != 0 && wpid != writer_pid) {
335*3cedbec3SEnji Cooper (void)unlink("testfifo");
336*3cedbec3SEnji Cooper errx(-1, "test_blocking_writer: waitpid %d returned %d",
337*3cedbec3SEnji Cooper writer_pid, wpid);
338*3cedbec3SEnji Cooper }
339*3cedbec3SEnji Cooper
340*3cedbec3SEnji Cooper if (wpid == writer_pid) {
341*3cedbec3SEnji Cooper (void)unlink("testfifo");
342*3cedbec3SEnji Cooper errx(-1, "test_blocking_writer: blocking child didn't "
343*3cedbec3SEnji Cooper "block");
344*3cedbec3SEnji Cooper }
345*3cedbec3SEnji Cooper
346*3cedbec3SEnji Cooper /*
347*3cedbec3SEnji Cooper * Unblock the blocking writer.
348*3cedbec3SEnji Cooper */
349*3cedbec3SEnji Cooper if (run_in_process(blocking_open_reader, &reader_pid,
350*3cedbec3SEnji Cooper "test_blocking_writer: blocking_open_reader") < 0) {
351*3cedbec3SEnji Cooper (void)unlink("testfifo");
352*3cedbec3SEnji Cooper (void)kill(writer_pid, SIGTERM);
353*3cedbec3SEnji Cooper (void)waitpid(writer_pid, &status, 0);
354*3cedbec3SEnji Cooper exit(-1);
355*3cedbec3SEnji Cooper }
356*3cedbec3SEnji Cooper
357*3cedbec3SEnji Cooper /*
358*3cedbec3SEnji Cooper * Make sure both processes exited quickly (<1 second) to make sure
359*3cedbec3SEnji Cooper * they didn't block, and GC.
360*3cedbec3SEnji Cooper */
361*3cedbec3SEnji Cooper if (wait_and_timeout(writer_pid, 1, &status,
362*3cedbec3SEnji Cooper "test_blocking_writer: blocking_open_writer") < 0) {
363*3cedbec3SEnji Cooper (void)unlink("testinfo");
364*3cedbec3SEnji Cooper (void)kill(writer_pid, SIGTERM);
365*3cedbec3SEnji Cooper (void)kill(reader_pid, SIGTERM);
366*3cedbec3SEnji Cooper (void)waitpid(writer_pid, &status, 0);
367*3cedbec3SEnji Cooper (void)waitpid(reader_pid, &status, 0);
368*3cedbec3SEnji Cooper exit(-1);
369*3cedbec3SEnji Cooper }
370*3cedbec3SEnji Cooper
371*3cedbec3SEnji Cooper if (wait_and_timeout(reader_pid, 1, &status,
372*3cedbec3SEnji Cooper "test_blocking_writer: blocking_open_reader") < 0) {
373*3cedbec3SEnji Cooper (void)unlink("testinfo");
374*3cedbec3SEnji Cooper (void)kill(reader_pid, SIGTERM);
375*3cedbec3SEnji Cooper (void)waitpid(reader_pid, &status, 0);
376*3cedbec3SEnji Cooper exit(-1);
377*3cedbec3SEnji Cooper }
378*3cedbec3SEnji Cooper
379*3cedbec3SEnji Cooper if (unlink("testfifo") < 0)
380*3cedbec3SEnji Cooper err(-1, "test_blocking_writer: unlink: testfifo");
381*3cedbec3SEnji Cooper }
382*3cedbec3SEnji Cooper
383*3cedbec3SEnji Cooper static void
test_non_blocking_reader(void)384*3cedbec3SEnji Cooper test_non_blocking_reader(void)
385*3cedbec3SEnji Cooper {
386*3cedbec3SEnji Cooper int status;
387*3cedbec3SEnji Cooper pid_t pid;
388*3cedbec3SEnji Cooper
389*3cedbec3SEnji Cooper if (mkfifo("testfifo", 0600) < 0)
390*3cedbec3SEnji Cooper err(-1, "test_non_blocking_reader: mkfifo: testfifo");
391*3cedbec3SEnji Cooper
392*3cedbec3SEnji Cooper if (run_in_process(non_blocking_open_reader, &pid,
393*3cedbec3SEnji Cooper "test_non_blocking_reader: non_blocking_open_reader") < 0) {
394*3cedbec3SEnji Cooper (void)unlink("testfifo");
395*3cedbec3SEnji Cooper exit(-1);
396*3cedbec3SEnji Cooper }
397*3cedbec3SEnji Cooper
398*3cedbec3SEnji Cooper status = -1;
399*3cedbec3SEnji Cooper if (wait_and_timeout(pid, 5, &status,
400*3cedbec3SEnji Cooper "test_non_blocking_reader: non_blocking_open_reader") < 0) {
401*3cedbec3SEnji Cooper (void)unlink("testfifo");
402*3cedbec3SEnji Cooper exit(-1);
403*3cedbec3SEnji Cooper }
404*3cedbec3SEnji Cooper
405*3cedbec3SEnji Cooper if (WEXITSTATUS(status) != 0) {
406*3cedbec3SEnji Cooper (void)unlink("testfifo");
407*3cedbec3SEnji Cooper errno = WEXITSTATUS(status);
408*3cedbec3SEnji Cooper err(-1, "test_non_blocking_reader: "
409*3cedbec3SEnji Cooper "non_blocking_open_reader: open: testfifo");
410*3cedbec3SEnji Cooper }
411*3cedbec3SEnji Cooper
412*3cedbec3SEnji Cooper if (unlink("testfifo") < 0)
413*3cedbec3SEnji Cooper err(-1, "test_non_blocking_reader: unlink: testfifo");
414*3cedbec3SEnji Cooper }
415*3cedbec3SEnji Cooper
416*3cedbec3SEnji Cooper static void
test_non_blocking_writer(void)417*3cedbec3SEnji Cooper test_non_blocking_writer(void)
418*3cedbec3SEnji Cooper {
419*3cedbec3SEnji Cooper int status;
420*3cedbec3SEnji Cooper pid_t pid;
421*3cedbec3SEnji Cooper
422*3cedbec3SEnji Cooper if (mkfifo("testfifo", 0600) < 0)
423*3cedbec3SEnji Cooper err(-1, "test_non_blocking_writer: mkfifo: testfifo");
424*3cedbec3SEnji Cooper
425*3cedbec3SEnji Cooper if (run_in_process(non_blocking_open_writer, &pid,
426*3cedbec3SEnji Cooper "test_non_blocking_writer: non_blocking_open_writer") < 0) {
427*3cedbec3SEnji Cooper (void)unlink("testfifo");
428*3cedbec3SEnji Cooper exit(-1);
429*3cedbec3SEnji Cooper }
430*3cedbec3SEnji Cooper
431*3cedbec3SEnji Cooper status = -1;
432*3cedbec3SEnji Cooper if (wait_and_timeout(pid, 5, &status,
433*3cedbec3SEnji Cooper "test_non_blocking_writer: non_blocking_open_writer") < 0) {
434*3cedbec3SEnji Cooper (void)unlink("testfifo");
435*3cedbec3SEnji Cooper exit(-1);
436*3cedbec3SEnji Cooper }
437*3cedbec3SEnji Cooper
438*3cedbec3SEnji Cooper if (WEXITSTATUS(status) != ENXIO) {
439*3cedbec3SEnji Cooper (void)unlink("testfifo");
440*3cedbec3SEnji Cooper
441*3cedbec3SEnji Cooper errno = WEXITSTATUS(status);
442*3cedbec3SEnji Cooper if (errno == 0)
443*3cedbec3SEnji Cooper errx(-1, "test_non_blocking_writer: "
444*3cedbec3SEnji Cooper "non_blocking_open_writer: open succeeded");
445*3cedbec3SEnji Cooper err(-1, "test_non_blocking_writer: "
446*3cedbec3SEnji Cooper "non_blocking_open_writer: open: testfifo");
447*3cedbec3SEnji Cooper }
448*3cedbec3SEnji Cooper
449*3cedbec3SEnji Cooper if (unlink("testfifo") < 0)
450*3cedbec3SEnji Cooper err(-1, "test_non_blocking_writer: unlink: testfifo");
451*3cedbec3SEnji Cooper }
452*3cedbec3SEnji Cooper
453*3cedbec3SEnji Cooper int
main(void)454*3cedbec3SEnji Cooper main(void)
455*3cedbec3SEnji Cooper {
456*3cedbec3SEnji Cooper
457*3cedbec3SEnji Cooper if (geteuid() != 0)
458*3cedbec3SEnji Cooper errx(-1, "must be run as root");
459*3cedbec3SEnji Cooper
460*3cedbec3SEnji Cooper strcpy(temp_dir, "fifo_open.XXXXXXXXXXX");
461*3cedbec3SEnji Cooper if (mkdtemp(temp_dir) == NULL)
462*3cedbec3SEnji Cooper err(-1, "mkdtemp");
463*3cedbec3SEnji Cooper if (chdir(temp_dir) < 0)
464*3cedbec3SEnji Cooper err(-1, "chdir: %s", temp_dir);
465*3cedbec3SEnji Cooper atexit(atexit_temp_dir);
466*3cedbec3SEnji Cooper
467*3cedbec3SEnji Cooper test_non_blocking_reader();
468*3cedbec3SEnji Cooper test_non_blocking_writer();
469*3cedbec3SEnji Cooper
470*3cedbec3SEnji Cooper test_blocking_reader();
471*3cedbec3SEnji Cooper test_blocking_writer();
472*3cedbec3SEnji Cooper
473*3cedbec3SEnji Cooper return (0);
474*3cedbec3SEnji Cooper }
475