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), poll(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/mkfifo7.c 38mycc -o mkfifo7 -Wall -Wextra -O0 -g mkfifo7.c || exit 1 39rm -f mkfifo7.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/mkfifo7 $fifo 48s=$? 49cd $odir 50 51while mount | grep "on $mntpoint " | grep -q tmpfs; do 52 umount $mntpoint || sleep 1 53done 54rm -rf /tmp/mkfifo7 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 <poll.h> 67#include <signal.h> 68#include <stdio.h> 69#include <stdlib.h> 70#include <time.h> 71#include <unistd.h> 72 73static char *path; 74 75#define PARALLEL 1 76 77static void 78reader(void) 79{ 80 struct pollfd pfd; 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 pfd.fd = fd; 95 pfd.events = POLLIN; 96 if ((n = poll(&pfd, 1, 0)) == -1) 97 err(1, "poll()"); 98 if (n == 1) { 99 r = read(fd, &ch, 1); 100 if (r == -1) 101 err(1, "read"); 102 if (r != 0) 103 fprintf(stderr, "read(1): %c\n", ch); 104 else 105 fprintf(stderr, "read(1): EOF\n"); 106 } 107 108 /* timeout */ 109 ch = 'z'; 110 if ((n = poll(&pfd, 1, 7000)) == -1) 111 err(1, "poll()"); 112 if (n != 1) 113 fprintf(stderr, "FAIL Expected n == 1, got %d\n", n); 114 if (n == 1) { 115 r = read(fd, &ch, 1); 116 if (r == -1) 117 err(1, "read"); 118 if (r == 0) 119 fprintf(stderr, "read(2): EOF\n"); 120 } 121 122 /* timeout */ 123 ch = 'z'; 124 if ((n = poll(&pfd, 1, 7000)) == -1) 125 err(1, "poll()"); 126 if (n != 1) 127 fprintf(stderr, "FAIL Expected n == 1, got %d\n", n); 128 if (n == 1) { 129 r = read(fd, &ch, 1); 130 if (r == -1) 131 err(1, "read"); 132 if (r != 0) 133 fprintf(stderr, "read(3): %c\n", ch); 134 } 135 136 if (close(fd) == -1) 137 err(1, "close() in child"); 138 _exit(n == 1 ? 0 : 1); 139} 140 141static void 142writer(void) 143{ 144 int fd; 145 146 do { 147 if ((fd = open(path, O_WRONLY)) == -1) 148 if (errno != EINTR) 149 err(1, "open(%s, O_WRONLY)", 150 path); 151 if (fd == -1) 152 warn("open(%s) wr", path); 153 } while (fd == -1); 154 if (write(fd, "a", 1) != 1) 155 err(1, "write one"); 156 if (close(fd) == -1) 157 warn("close() in parent"); 158} 159 160static void 161test(void) 162{ 163 pid_t pid; 164 int status; 165 166 if ((pid = fork()) == 0) 167 reader(); 168 writer(); 169 170 if (waitpid(pid, &status, 0) != pid) 171 err(1, "waitpid(%d)", pid); 172 173 _exit(status != 0); 174} 175 176int 177main(int argc __unused, char *argv[]) 178{ 179 int e, i, pids[PARALLEL], status; 180 181 if (argc != 2) { 182 fprintf(stderr, "Usage: %s <fifo file>\n", argv[0]); 183 exit(1); 184 } 185 path = argv[1]; 186 e = 0; 187 188 unlink(path); 189 if (mkfifo(path, 0640) == -1) 190 err(1, "mkfifo(%s)", path); 191 192 for (i = 0; i < PARALLEL; i++) { 193 if ((pids[i] = fork()) == 0) 194 test(); 195 } 196 for (i = 0; i < PARALLEL; i++) { 197 if (waitpid(pids[i], &status, 0) == -1) 198 err(1, "waitpid(%d)", pids[i]); 199 e += status == 0 ? 0 : 1; 200 } 201 202 return (e); 203} 204