1#!/bin/sh 2 3# 4# Copyright (c) 2016 EMC Corp. 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# No problems seen 30# Stand alone version of testcases/tcp 31 32. ../default.cfg 33 34dir=/tmp 35odir=`pwd` 36cd $dir 37sed '1,/^EOF/d' < $odir/$0 > $dir/tcp3.c 38mycc -o tcp3 -Wall -Wextra -O0 -g tcp3.c || exit 1 39rm -f tcp3.c 40 41daemon sh -c "(cd $odir/../testcases/swap; ./swap -t 5m)" > /dev/null 2>&1 42timeout 2m /tmp/tcp3 43s=$? 44while pgrep -q swap; do 45 pkill -9 swap 46done 47 48if pgrep -q tcp3; then 49 echo FAIL 50 pgrep tcp3 | while read pid; do 51 ps -lp$pid 52 procstat -kk $pid 53 done 54 exit 1 55fi 56rm -rf /tmp/tcp3 /tmp/tcp3.c 57exit $s 58 59EOF 60#include <sys/param.h> 61#include <sys/mman.h> 62#include <sys/socket.h> 63#include <sys/stat.h> 64#include <sys/wait.h> 65 66#include <netinet/in.h> 67 68#include <machine/atomic.h> 69 70#include <err.h> 71#include <errno.h> 72#include <fcntl.h> 73#include <netdb.h> 74#include <signal.h> 75#include <stdio.h> 76#include <stdlib.h> 77#include <string.h> 78#include <time.h> 79#include <unistd.h> 80 81#define NB (400 * 1024 * 1024) 82#define SYNC 0 83#define PARALLEL 8 84#define RUNTIME (1 * 60) 85 86static sig_atomic_t done_testing; 87static volatile u_int *share; 88static int bufsize; 89static int port; 90 91static void 92alarm_handler(int i __unused) 93{ 94 95 done_testing++; 96} 97 98static void 99exit_handler(int i __unused) 100{ 101 102 _exit(1); 103} 104 105static void 106callcleanup(void) 107{ 108} 109 110static int 111random_int(int mi, int ma) 112{ 113 return (arc4random() % (ma - mi + 1) + mi); 114} 115 116static void 117reader(void) { 118 struct sockaddr_in inetaddr, inetpeer; 119 socklen_t len; 120 int n, *buf; 121 int on; 122 int tcpsock, msgsock; 123 124 on = 1; 125 if ((tcpsock = socket(AF_INET, SOCK_STREAM, 0)) < 0) 126 err(1, "socket(), %s:%d", __FILE__, __LINE__); 127 128 if (setsockopt(tcpsock, 129 SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) 130 err(1, "setsockopt(), %s:%d", __FILE__, __LINE__); 131 132 inetaddr.sin_family = AF_INET; 133 inetaddr.sin_addr.s_addr = INADDR_ANY; 134 inetaddr.sin_port = htons(port); 135 inetaddr.sin_len = sizeof(inetaddr); 136 137 if (bind(tcpsock, 138 (struct sockaddr *)&inetaddr, sizeof (inetaddr)) < 0) 139 err(1, "bind(), %s:%d", __FILE__, __LINE__); 140 141 if (listen(tcpsock, 5) < 0) 142 err(1, "listen(), %s:%d", __FILE__, __LINE__); 143 144 if (random_int(1,100) > 60) 145 sleep(6); 146 147 len = sizeof(inetpeer); 148 if ((msgsock = accept(tcpsock, 149 (struct sockaddr *)&inetpeer, &len)) < 0) 150 err(1, "accept(), %s:%d", __FILE__, __LINE__); 151 152 if ((buf = malloc(bufsize)) == NULL) 153 err(1, "malloc(%d), %s:%d", bufsize, __FILE__, 154 __LINE__); 155 while (done_testing == 0) { 156 if ((n = read(msgsock, buf, bufsize)) < 0) 157 err(1, "read(), %s:%d", __FILE__, __LINE__); 158 if (n == 0) break; 159 } 160 close(msgsock); 161 return; 162} 163 164static void 165writer(void) { 166 struct hostent *hostent; 167 struct sockaddr_in inetaddr; 168 int i, *buf, r; 169 int tcpsock, on; 170 171 on = 1; 172 for (i = 1; i < 5; i++) { 173 if ((tcpsock = socket(AF_INET, SOCK_STREAM, 0)) < 0) 174 err(1, "socket(), %s:%d", __FILE__, __LINE__); 175 176 if (setsockopt(tcpsock, 177 SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) 178 err(1, "setsockopt(), %s:%d", __FILE__, __LINE__); 179 180 hostent = gethostbyname ("localhost"); 181 bzero((char *) &inetaddr, sizeof(inetaddr)); 182 memcpy (&inetaddr.sin_addr.s_addr, hostent->h_addr, 183 sizeof (struct in_addr)); 184 185 inetaddr.sin_family = AF_INET; 186 inetaddr.sin_port = htons(port); 187 inetaddr.sin_len = sizeof(inetaddr); 188 189 r = connect(tcpsock, (struct sockaddr *) &inetaddr, 190 sizeof(inetaddr)); 191 if (r == 0) 192 break; 193 sleep(1); 194 close(tcpsock); 195 } 196 if (r < 0) 197 err(1, "connect(), %s:%d", __FILE__, __LINE__); 198 199 if ((buf = malloc(bufsize)) == NULL) 200 err(1, "malloc(%d), %s:%d", bufsize, __FILE__, 201 __LINE__); 202 for (i = 0; i < bufsize / (int)sizeof(int); i++) 203 buf[i] = i; 204 205 for (;;) { 206 for (i = 0; i < NB; i+= bufsize) { 207 if (write(tcpsock, buf, bufsize) < 0) { 208 if (errno == EPIPE) 209 return; 210 if (errno != ECONNRESET) 211 err(1, "write(%d), %s:%d", tcpsock, 212 __FILE__, __LINE__); 213 _exit(EXIT_SUCCESS); 214 } 215 } 216 } 217 return; 218} 219 220static int 221test2(void) 222{ 223 pid_t pid; 224 225 if ((pid = fork()) == 0) { 226 writer(); 227 _exit(EXIT_SUCCESS); 228 229 } else if (pid > 0) { 230 reader(); 231 kill(pid, SIGINT); 232 waitpid(pid, NULL, 0); 233 } else 234 err(1, "fork(), %s:%d", __FILE__, __LINE__); 235 236 return (0); 237} 238 239static void 240test(int nb) 241{ 242 atomic_add_int(&share[SYNC], 1); 243 while (share[SYNC] != PARALLEL) 244 ; 245 246 port = 12340 + nb; 247 bufsize = 2 << random_int(1, 12); 248 signal(SIGALRM, alarm_handler); 249 signal(SIGINT, exit_handler); 250 atexit(callcleanup); 251 252 alarm(2); 253 test2(); 254 255 _exit(0); 256} 257 258int 259main(void) 260{ 261 size_t len; 262 time_t start; 263 int e, i, pids[PARALLEL], status; 264 265 e = 0; 266 len = PAGE_SIZE; 267 if ((share = mmap(NULL, len, PROT_READ | PROT_WRITE, 268 MAP_ANON | MAP_SHARED, -1, 0)) == MAP_FAILED) 269 err(1, "mmap"); 270 271 start = time(NULL); 272 while ((time(NULL) - start) < RUNTIME && e == 0) { 273 share[SYNC] = 0; 274 for (i = 0; i < PARALLEL; i++) { 275 if ((pids[i] = fork()) == 0) 276 test(i); 277 } 278 for (i = 0; i < PARALLEL; i++) { 279 if (waitpid(pids[i], &status, 0) == -1) 280 err(1, "waitpid(%d)", pids[i]); 281 e += status == 0 ? 0 : 1; 282 } 283 } 284 285 return (e); 286} 287