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(4) 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/mkfifo6.c 38mycc -o mkfifo6 -Wall -Wextra -O0 -g mkfifo6.c || exit 1 39rm -f mkfifo6.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/mkfifo6 $fifo 48s=$? 49cd $odir 50 51while mount | grep "on $mntpoint " | grep -q tmpfs; do 52 umount $mntpoint || sleep 1 53done 54rm -rf /tmp/mkfifo6 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 /* timeout */ 94 ch = 'z'; 95 FD_ZERO(&rset); 96 FD_SET(fd, &rset); 97 timeout.tv_sec = 0; 98 timeout.tv_usec = 100000; 99 if ((n = select(fd + 1, &rset, NULL, NULL, &timeout)) < 0) 100 if (errno != EINTR) 101 err(1, "select()"); 102 if (n != 0) 103 fprintf(stderr, "FAIL Expected n == 0, got %d\n", n); 104 if (n == 1 && FD_ISSET(fd, &rset)) { 105 r = read(fd, &ch, 1); 106 if (r == -1) 107 err(1, "read"); 108 if (r != 0) 109 fprintf(stderr, "read(2): %c\n", ch); 110 else 111 fprintf(stderr, "read(2): EOF\n"); 112 } 113 114 sleep(3); 115 if (close(fd) == -1) 116 err(1, "close() in child"); 117 _exit(n); 118} 119 120static void 121writer(void) 122{ 123 int fd; 124 125 do { 126 if ((fd = open(path, O_WRONLY)) == -1) 127 if (errno != EINTR) 128 err(1, "open(%s, O_WRONLY)", 129 path); 130 if (fd == -1) 131 warn("open(%s) wr", path); 132 } while (fd == -1); 133 sleep(2); 134 if (write(fd, "a", 1) != 1) 135 err(1, "write one"); 136 if (close(fd) == -1) 137 warn("close() in parent"); 138} 139 140static void 141test(void) 142{ 143 pid_t pid; 144 int status; 145 146 if ((pid = fork()) == 0) 147 reader(); 148 writer(); 149 150 if (waitpid(pid, &status, 0) != pid) 151 err(1, "waitpid(%d)", pid); 152 153 _exit(status != 0); 154} 155 156int 157main(int argc __unused, char *argv[]) 158{ 159 int e, i, pids[PARALLEL], status; 160 161 if (argc != 2) { 162 fprintf(stderr, "Usage: %s <fifo file>\n", argv[0]); 163 exit(1); 164 } 165 path = argv[1]; 166 e = 0; 167 168 unlink(path); 169 if (mkfifo(path, 0640) == -1) 170 err(1, "mkfifo(%s)", path); 171 172 for (i = 0; i < PARALLEL; i++) { 173 if ((pids[i] = fork()) == 0) 174 test(); 175 } 176 for (i = 0; i < PARALLEL; i++) { 177 if (waitpid(pids[i], &status, 0) == -1) 178 err(1, "waitpid(%d)", pids[i]); 179 e += status == 0 ? 0 : 1; 180 } 181 182 return (e); 183} 184