xref: /freebsd/tools/test/stress2/misc/mkfifo5.sh (revision fd45b686f9d92f583366c75b22c04c7ee49709c0)
1#!/bin/sh
2
3#
4# Copyright (c) 2017 Dell EMC Isilon
5# All rights reserved.
6#
7# Redistribution and use in source and binary forms, with or without
8# modification, are permitted provided that the following conditions
9# are met:
10# 1. Redistributions of source code must retain the above copyright
11#    notice, this list of conditions and the following disclaimer.
12# 2. Redistributions in binary form must reproduce the above copyright
13#    notice, this list of conditions and the following disclaimer in the
14#    documentation and/or other materials provided with the distribution.
15#
16# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26# SUCH DAMAGE.
27#
28
29# mkfifo(2), select(2) with tmpfs(5) scenario.
30
31. ../default.cfg
32[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1
33
34dir=/tmp
35odir=`pwd`
36cd $dir
37sed '1,/^EOF/d' < $odir/$0 > $dir/mkfifo5.c
38mycc -o mkfifo5 -Wall -Wextra -O0 -g mkfifo5.c || exit 1
39rm -f mkfifo5.c
40cd $odir
41
42mount | grep -q "on $mntpoint " && umount -f $mntpoint
43mount -o size=1g -t tmpfs tmpfs $mntpoint
44
45fifo=$mntpoint/fifo.file
46cd $mntpoint
47/tmp/mkfifo5 $fifo
48s=$?
49cd $odir
50
51while mount | grep "on $mntpoint " | grep -q tmpfs; do
52	umount $mntpoint || sleep 1
53done
54rm -rf /tmp/mkfifo5
55exit $s
56
57EOF
58#include <sys/param.h>
59#include <sys/mman.h>
60#include <sys/stat.h>
61#include <sys/wait.h>
62
63#include <err.h>
64#include <errno.h>
65#include <fcntl.h>
66#include <signal.h>
67#include <stdio.h>
68#include <stdlib.h>
69#include <time.h>
70#include <unistd.h>
71
72static char *path;
73
74#define PARALLEL 1
75
76static void
77reader(void)
78{
79	fd_set rset;
80	struct timeval timeout;
81	int fd, n, r;
82	char ch;
83
84	do {
85		if((fd = open(path, O_RDONLY)) == -1)
86			if (errno != EINTR)
87				err(1, "open(%s, O_RDONLY)",
88				    path);
89		if (fd == -1)
90			warn("open(%s) ro", path);
91	} while (fd == -1);
92
93	/* Read one character */
94	FD_ZERO(&rset);
95	FD_SET(fd, &rset);
96	if ((n = select(fd + 1, &rset, NULL, NULL, NULL)) < 0)
97		if (errno != EINTR)
98			err(1, "select()");
99	if (n == 1 && FD_ISSET(fd, &rset)) {
100		r = read(fd, &ch, 1);
101		if (r == -1)
102			err(1, "read");
103		if (r == 0)
104			fprintf(stderr, "read(1): EOF\n");
105	}
106
107	/* timeout */
108	ch = 'z';
109	FD_ZERO(&rset);
110	FD_SET(fd, &rset);
111	timeout.tv_sec  = 1;
112	timeout.tv_usec = 0;
113	if ((n = select(fd + 1, &rset, NULL, NULL, &timeout)) < 0)
114		if (errno != EINTR)
115			err(1, "select()");
116	if (n != 1)
117		fprintf(stderr, "FAIL Expected n == 0, got %d\n", n);
118	if (n == 1 && FD_ISSET(fd, &rset)) {
119		r = read(fd, &ch, 1);
120		if (r == -1)
121			err(1, "read");
122		if (r == 0)
123			fprintf(stderr, "read(2): EOF\n");
124	}
125
126	/* timeout */
127	ch = 'z';
128	FD_ZERO(&rset);
129	FD_SET(fd, &rset);
130	timeout.tv_sec  = 1;
131	timeout.tv_usec = 0;
132	if ((n = select(fd + 1, &rset, NULL, NULL, &timeout)) < 0)
133		if (errno != EINTR)
134			err(1, "select()");
135	if (n != 1)
136		fprintf(stderr, "FAIL Expected n == 0, got %d\n", n);
137	if (n == 1 && FD_ISSET(fd, &rset)) {
138		r = read(fd, &ch, 1);
139		if (r == -1)
140			err(1, "read");
141		if (r != 0)
142			fprintf(stderr, "read(3): %c\n", ch);
143	}
144
145	if (close(fd) == -1)
146		err(1, "close() in child");
147	_exit(n == 1 ? 0 : 1);
148}
149
150static void
151writer(void)
152{
153	int fd;
154
155	do {
156		if ((fd = open(path, O_WRONLY)) == -1)
157			if (errno != EINTR)
158				err(1, "open(%s, O_WRONLY)",
159				    path);
160		if (fd == -1)
161			warn("open(%s) wr", path);
162	} while (fd == -1);
163	if (write(fd, "a", 1) != 1)
164		err(1, "write one");
165	if (write(fd, "b", 1) != 1)
166		err(1, "write one");
167	if (close(fd) == -1)
168		warn("close() in parent");
169}
170
171static void
172test(void)
173{
174	pid_t pid;
175	int status;
176
177	if ((pid = fork()) == 0)
178		reader();
179	writer();
180
181	if (waitpid(pid, &status, 0) != pid)
182		err(1, "waitpid(%d)", pid);
183
184	_exit(status != 0);
185}
186
187int
188main(int argc __unused, char *argv[])
189{
190	int e, i, pids[PARALLEL], status;
191
192	if (argc != 2) {
193		fprintf(stderr, "Usage: %s <fifo file>\n", argv[0]);
194		exit(1);
195	}
196	path = argv[1];
197	e = 0;
198
199	unlink(path);
200	if (mkfifo(path, 0640) == -1)
201		err(1, "mkfifo(%s)", path);
202
203	for (i = 0; i < PARALLEL; i++) {
204		if ((pids[i] = fork()) == 0)
205			test();
206	}
207	for (i = 0; i < PARALLEL; i++) {
208		if (waitpid(pids[i], &status, 0) == -1)
209			err(1, "waitpid(%d)", pids[i]);
210		e += status == 0 ? 0 : 1;
211	}
212
213	return (e);
214}
215