delorie.com/archives/browse.cgi   search  
Mail Archives: cygwin/2013/04/26/12:26:00

X-Recipient: archive-cygwin AT delorie DOT com
DomainKey-Signature: a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id
:list-unsubscribe:list-subscribe:list-archive:list-post
:list-help:sender:message-id:date:from:mime-version:to:subject
:content-type; q=dns; s=default; b=eT7Ka7BGJhD/ZtzqHAovUtInznv2d
VS0UO+NJFi1Bc8EZ6n+SAU8haCoV7QwN335GCg91QQ79XBUhBlKLPmNQ6JEHOHgV
K8aAsY6INrce84Eny1papxQm80czyHxvhyYocAcVb0DkMjrcP8ugDxU1Pn7tlm/T
hXtpc7yhs0c2aY=
DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id
:list-unsubscribe:list-subscribe:list-archive:list-post
:list-help:sender:message-id:date:from:mime-version:to:subject
:content-type; s=default; bh=3C6fQdPMq3ByIhYWG3SAZYpdYDQ=; b=OCc
GwPBx8AjNC659AFsqiyzBF6fSddSjQkS61dL6jzmocyUTs8+um4fyzoFNT2r1quz
q/jWmmmek8szbeKUclbkgSKDSsId4lRicVvo6gbaKHHhGIbsZt5/DWqjbbJHKC7G
r2JjNf2igAa5tWCrb0US9bil/5wmDZaKF+6Ob4Io=
Mailing-List: contact cygwin-help AT cygwin DOT com; run by ezmlm
List-Id: <cygwin.cygwin.com>
List-Subscribe: <mailto:cygwin-subscribe AT cygwin DOT com>
List-Archive: <http://sourceware.org/ml/cygwin/>
List-Post: <mailto:cygwin AT cygwin DOT com>
List-Help: <mailto:cygwin-help AT cygwin DOT com>, <http://sourceware.org/ml/#faqs>
Sender: cygwin-owner AT cygwin DOT com
Mail-Followup-To: cygwin AT cygwin DOT com
Delivered-To: mailing list cygwin AT cygwin DOT com
X-Spam-SWARE-Status: No, score=-3.9 required=5.0 tests=AWL,BAYES_00,RCVD_IN_DNSWL_NONE,RCVD_IN_HOSTKARMA_W,RCVD_IN_HOSTKARMA_WL,RCVD_IN_HOSTKARMA_YE,SPF_PASS autolearn=ham version=3.3.1
Message-ID: <517AAA86.9030506@acm.org>
Date: Fri, 26 Apr 2013 09:25:42 -0700
From: David Rothenberger <daveroth AT acm DOT org>
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:17.0) Gecko/20130328 Thunderbird/17.0.5
MIME-Version: 1.0
To: cygwin <cygwin AT cygwin DOT com>
Subject: STC for libapr1 flock failure
X-Virus-Found: No

--------------030907050300000405040907
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit

The libapr1 test cases are failing for flock locks. I've extracted
the attached STC to demonstrate the problem. It starts a number of
child processes, each of which repeatedly grab and release a lock on
a temporary file. While they have the lock, the increment a counter
in shared memory in a racy way.

If all goes well, the counter should end up having the value of
CHILDREN * ITERS_PER_CHILDREN. And it does, except sometimes the
test just hangs. The attached runs the test 10 times, which is
sufficient to reproduce the hang on my machine. Sometimes the first
iteration hangs, sometimes it's the last one.

This was working the last time I built libapr1 (19-Feb-2012).

To run the test, just run "make".

Regards,
David

-- 
David Rothenberger  ----  daveroth AT acm DOT org

question = ( to ) ? be : ! be;
                -- Wm. Shakespeare

--------------030907050300000405040907
Content-Type: text/plain; charset=windows-1252;
 name="Makefile"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename="Makefile"

CC=gcc
CFLAGS=-Wall
STC=stc-flock-fork

.PHONY: test
test: $(STC)
	./$(STC)

$(STC): $(STC).c
	$(CC) $(CFLAGS) -o $@ $^

.PHONY: clean
clean:
	rm -f $(STC)
	-rm -f /tmp/flocktst*

--------------030907050300000405040907
Content-Type: text/plain; charset=windows-1252;
 name="stc-flock-fork.c"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename="stc-flock-fork.c"

/***********************************************************************
 * This is a STC to show that flock occasionally does not work.
 *
 * It tries to use flock() for file locking. It creates a temporary
 * file, the uses fork to spawn a number of children. Each child opens
 * the file, then repeatedly uses flock to lock and unlock it.
 *
 * While each child has the lock, it increments a counter stored in
 * shared memory in a racy way, passing the current value to a function
 * which sleeps briefly, then returns the incremented counter.
 *
 * If all works correctly, the counter should end up be incremented
 * by each child iteration.
 *
 * However, this is failing for me occasionally. The test case hangs after a
   few iterations.
 *
 * This test was extracted from the APR test suite.
 *
 * Compile: gcc -Wall -o stc-flock-fork stc-flock-fork.c
 ***********************************************************************/

#include <sys/types.h>
#include <sys/file.h>
#include <sys/wait.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/mman.h>

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>

#define MAX_ITER 10
#define CHILDREN 6
#define MAX_COUNT (MAX_ITER * CHILDREN)

/* Counter stored in shared memory. */
static volatile int *x;

/* A temporary file used for flock. */
char tmpfilename[] = "/tmp/flocktstXXXXXX";

/* a slower more racy way to implement (*x)++ */
static int increment(int n)
{
    usleep(1);
    return n+1;
}

/* Fork and use flock to lock and unlock the file repeatedly in the child. */
void make_child(int trylock, pid_t *pid)
{
    if ((*pid = fork()) < 0) {
        perror("fork failed");
        exit(1);
    }
    else if (*pid == 0) {
        int fd2 = open(tmpfilename, O_RDONLY);
        if (fd2 < 0) {
            perror("child open");
            exit(1);
        }

        int rc;
        int i;
        for (i=0; i<MAX_ITER; ++i) {
            /* Get the lock. */
            do {
                rc = flock(fd2, LOCK_EX);
            } while (rc < 0 && errno == EINTR);
            if (rc < 0) {
                perror("lock");
                exit(1);
            }

            /* Have the lock. Increment the counter. */
            *x = increment(*x);

            /* Release the lock. */
            do {
                rc = flock(fd2, LOCK_UN);
            } while (rc < 0 && errno == EINTR);
            if (rc < 0) {
                perror("unlock");
                exit(1);
            }
        }
        exit(0);
    }
}

/* Wait for the child to finish. */
void await_child(pid_t pid)
{
    pid_t pstatus;
    int exit_int;

    do {
        pstatus = waitpid(pid, &exit_int, WUNTRACED);
    } while (pstatus < 0 && errno == EINTR);
}

/* Allocate and attach shared memory */
void init_shm ()
{
    x = mmap(NULL, getpagesize(), PROT_READ | PROT_WRITE,
             MAP_SHARED | MAP_ANONYMOUS, -1, 0);
    if (!x) {
        perror ("mmap failed");
        exit (1);
    }
}

int main(int argc, const char * const * argv, const char * const *env)
{
    pid_t child[CHILDREN];
    int i;
    int n;
    int fd;

    /* Create the temporary file. */
    fd = mkstemp(tmpfilename);
    if (fd < 0) {
        perror("open failed");
        exit(1);
    }
    close(fd);

    /* Initialize shared memory */
    init_shm();

    /* Perform the test multiple times, since this fails only intermittedly. */
    for (i = 0; i < 10; ++i) {
        printf("Iteration %d\n", i);

        /* Initialize counter */
        *x = 0;

        /* Create the children. */
        for (n = 0; n < CHILDREN; n++)
            make_child(0, &child[n]);

        /* Wait for them to finish. */
        for (n = 0; n < CHILDREN; n++)
            await_child(child[n]);

        /* Check counter */
        if (*x != MAX_COUNT) {
            printf("Iteration %d: FAILED: *x (%d) != MAX_COUNT (%d)\n", i, *x, MAX_COUNT);
            exit(1);
        }
    }

    /* Clean up. */
    unlink(tmpfilename);

    return 0;
}


--------------030907050300000405040907
Content-Type: text/plain; charset=us-ascii

--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
--------------030907050300000405040907--

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019