1*8a272653SPeter Holm#!/bin/sh 2*8a272653SPeter Holm 3*8a272653SPeter Holm# 4*8a272653SPeter Holm# Copyright (c) 2012 Peter Holm <pho@FreeBSD.org> 5*8a272653SPeter Holm# All rights reserved. 6*8a272653SPeter Holm# 7*8a272653SPeter Holm# Redistribution and use in source and binary forms, with or without 8*8a272653SPeter Holm# modification, are permitted provided that the following conditions 9*8a272653SPeter Holm# are met: 10*8a272653SPeter Holm# 1. Redistributions of source code must retain the above copyright 11*8a272653SPeter Holm# notice, this list of conditions and the following disclaimer. 12*8a272653SPeter Holm# 2. Redistributions in binary form must reproduce the above copyright 13*8a272653SPeter Holm# notice, this list of conditions and the following disclaimer in the 14*8a272653SPeter Holm# documentation and/or other materials provided with the distribution. 15*8a272653SPeter Holm# 16*8a272653SPeter Holm# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17*8a272653SPeter Holm# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18*8a272653SPeter Holm# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19*8a272653SPeter Holm# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20*8a272653SPeter Holm# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21*8a272653SPeter Holm# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22*8a272653SPeter Holm# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23*8a272653SPeter Holm# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24*8a272653SPeter Holm# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25*8a272653SPeter Holm# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26*8a272653SPeter Holm# SUCH DAMAGE. 27*8a272653SPeter Holm# 28*8a272653SPeter Holm 29*8a272653SPeter Holm# Problem seen with atomic assignment of f_offset. Fixed in r238029. 30*8a272653SPeter Holm 31*8a272653SPeter Holm# Test scenario by kib@ 32*8a272653SPeter Holm 33*8a272653SPeter Holm. ../default.cfg 34*8a272653SPeter Holm 35*8a272653SPeter Holmhere=`pwd` 36*8a272653SPeter Holmcd /tmp 37*8a272653SPeter Holmsed '1,/^EOF/d' < $here/$0 > f_offset.c 38*8a272653SPeter Holmmycc -o f_offset -Wall -Wextra -O2 f_offset.c -lpthread 39*8a272653SPeter Holmrm -f f_offset.c 40*8a272653SPeter Holm 41*8a272653SPeter Holm/tmp/f_offset 42*8a272653SPeter Holm 43*8a272653SPeter Holmrm -f /tmp/f_offset 44*8a272653SPeter Holmexit 0 45*8a272653SPeter HolmEOF 46*8a272653SPeter Holm/* 47*8a272653SPeter Holm Description by kib: 48*8a272653SPeter HolmTo really exercise the race conditions, all the following items must 49*8a272653SPeter Holmbe fulfilled simultaneously: 50*8a272653SPeter Holm1. you use 32bit host, i.e. i386 51*8a272653SPeter Holm2. you operate on the file offsets larger than 4GB (but see below) 52*8a272653SPeter Holm3. there are several threads or processes that operate on the same 53*8a272653SPeter Holm file descriptor simultaneously. 54*8a272653SPeter Holm 55*8a272653SPeter HolmPlease note that the normal fork(2) causes file descriptor table 56*8a272653SPeter Holmcopy, so only rfork(2) call with RFFDG flag unset causes sharing. Or, 57*8a272653SPeter Holmmulti-threading can be used. 58*8a272653SPeter Holm */ 59*8a272653SPeter Holm 60*8a272653SPeter Holm#include <err.h> 61*8a272653SPeter Holm#include <fcntl.h> 62*8a272653SPeter Holm#include <pthread.h> 63*8a272653SPeter Holm#include <stdio.h> 64*8a272653SPeter Holm#include <stdlib.h> 65*8a272653SPeter Holm#include <string.h> 66*8a272653SPeter Holm#include <sys/types.h> 67*8a272653SPeter Holm#include <unistd.h> 68*8a272653SPeter Holm 69*8a272653SPeter Holmint errors, fd; 70*8a272653SPeter Holmchar file[128]; 71*8a272653SPeter Holm 72*8a272653SPeter Holm#define START 0x100000000ULL 73*8a272653SPeter Holm#define N 1000000 74*8a272653SPeter Holm 75*8a272653SPeter Holmvoid * 76*8a272653SPeter Holmt1(void *arg __unused) 77*8a272653SPeter Holm{ 78*8a272653SPeter Holm int i; 79*8a272653SPeter Holm off_t offset; 80*8a272653SPeter Holm 81*8a272653SPeter Holm offset = START + 2; 82*8a272653SPeter Holm 83*8a272653SPeter Holm for (i = 0; i < N; i++) { 84*8a272653SPeter Holm if (lseek(fd, offset, SEEK_SET) == -1) 85*8a272653SPeter Holm err(1, "lseek error"); 86*8a272653SPeter Holm } 87*8a272653SPeter Holm 88*8a272653SPeter Holm return (0); 89*8a272653SPeter Holm} 90*8a272653SPeter Holm 91*8a272653SPeter Holmvoid * 92*8a272653SPeter Holmt2(void *arg __unused) 93*8a272653SPeter Holm{ 94*8a272653SPeter Holm int i; 95*8a272653SPeter Holm off_t offset; 96*8a272653SPeter Holm 97*8a272653SPeter Holm offset = 1; 98*8a272653SPeter Holm 99*8a272653SPeter Holm for (i = 0; i < N; i++) { 100*8a272653SPeter Holm if (lseek(fd, offset, SEEK_SET) == -1) 101*8a272653SPeter Holm err(1, "lseek error"); 102*8a272653SPeter Holm } 103*8a272653SPeter Holm return (0); 104*8a272653SPeter Holm} 105*8a272653SPeter Holmvoid * 106*8a272653SPeter Holmt3(void *arg __unused) 107*8a272653SPeter Holm{ 108*8a272653SPeter Holm int i; 109*8a272653SPeter Holm off_t offset; 110*8a272653SPeter Holm 111*8a272653SPeter Holm offset = 1; 112*8a272653SPeter Holm 113*8a272653SPeter Holm for (i = 0; i < N; i++) { 114*8a272653SPeter Holm if ((offset = lseek(fd, 0, SEEK_CUR)) == -1) 115*8a272653SPeter Holm err(1, "lseek error"); 116*8a272653SPeter Holm if (offset != 1 && offset != START + 2) 117*8a272653SPeter Holm fprintf(stderr, "FAIL #%d offset = %10jd (0x%09jx)\n", 118*8a272653SPeter Holm errors++, offset, offset); 119*8a272653SPeter Holm } 120*8a272653SPeter Holm 121*8a272653SPeter Holm return (0); 122*8a272653SPeter Holm} 123*8a272653SPeter Holm 124*8a272653SPeter Holmint 125*8a272653SPeter Holmmain(void) 126*8a272653SPeter Holm{ 127*8a272653SPeter Holm pthread_t threads[3]; 128*8a272653SPeter Holm int r; 129*8a272653SPeter Holm int i; 130*8a272653SPeter Holm off_t offset; 131*8a272653SPeter Holm 132*8a272653SPeter Holm snprintf(file, sizeof(file), "file.%06d", getpid()); 133*8a272653SPeter Holm if ((fd = open(file, O_RDWR | O_CREAT | O_TRUNC, 0600)) < 0) 134*8a272653SPeter Holm err(1, "%s", file); 135*8a272653SPeter Holm 136*8a272653SPeter Holm offset = 1; 137*8a272653SPeter Holm if (lseek(fd, offset, SEEK_SET) == -1) 138*8a272653SPeter Holm err(1, "lseek error"); 139*8a272653SPeter Holm 140*8a272653SPeter Holm for (i = 0; i < 20 && errors < 10; i++) { 141*8a272653SPeter Holm if ((r = pthread_create(&threads[0], NULL, t1, 0)) != 0) 142*8a272653SPeter Holm errc(1, r, "pthread_create()"); 143*8a272653SPeter Holm if ((r = pthread_create(&threads[1], NULL, t2, 0)) != 0) 144*8a272653SPeter Holm errc(1, r, "pthread_create()"); 145*8a272653SPeter Holm if ((r = pthread_create(&threads[2], NULL, t3, 0)) != 0) 146*8a272653SPeter Holm errc(1, r, "pthread_create()"); 147*8a272653SPeter Holm 148*8a272653SPeter Holm if ((r = pthread_join(threads[0], NULL)) != 0) 149*8a272653SPeter Holm errc(1, r, "pthread_join(%d)", 0); 150*8a272653SPeter Holm if ((r = pthread_join(threads[1], NULL)) != 0) 151*8a272653SPeter Holm errc(1, r, "pthread_join(%d)", 1); 152*8a272653SPeter Holm if ((r = pthread_join(threads[2], NULL)) != 0) 153*8a272653SPeter Holm errc(1, r, "pthread_join(%d)", 2); 154*8a272653SPeter Holm } 155*8a272653SPeter Holm close(fd); 156*8a272653SPeter Holm if (unlink(file) == -1) 157*8a272653SPeter Holm err(3, "unlink(%s)", file); 158*8a272653SPeter Holm 159*8a272653SPeter Holm return (0); 160*8a272653SPeter Holm} 161