On 2/14/2012 10:24 AM, Corinna Vinschen wrote:
> On Feb 14 09:58, David Rothenberger wrote:
>> On 2/14/2012 6:45 AM, Corinna Vinschen wrote:
>>> On Feb 14 15:02, Corinna Vinschen wrote:
>>>> On Feb 14 00:00, David Rothenberger wrote:
>>>>> The libapr1 test cases are failing again for flock locks. This same
>>>>> test case failed with 1.7.9 with a fatal error[1], but that was
>>>>> corrected. The test is no longer encountering the fatal error, but
>>>>> it is producing the wrong result.
>>>>
>>>> Thanks for the testcase.  I think I found the issue.  An event handle
>>>> was closed in the wrong place, outside of the important mutex lock for
>>>> the lock object.  I applied the patch to CVS.  Your testcase now appears
>>>> to run fine for me.  Can you try your entire testsuite again and see
>>>> if there's another failure lurking?
>>>
>>> I uploaded a snapshot for testing.
>>
>> Thanks. The snapshot fixes the flock test case, but now the fcntl test
>> case is failing.
> 
> *Sob*.  How so?  Does it hang or does it allow multiple concurrent
> exclusive locks as the flock case?

Sorry, I should have said. It hangs.

>> I'll try to send an STC for that case, but I suspect the one from last
>> year will have the problem.
> 
> Please send it anyway.

It's attached. If you run it with an argument (any argument), each child
will print its loop count and you can see what happens. If it doesn't
hang for you, try increasing MAX_ITER or CHILDREN at the top.



-- 
David Rothenberger  ----  daver...@acm.org

QOTD:
        "Oh, no, no...  I'm not beautiful.  Just very, very pretty."
/***********************************************************************
 * This is a STC to show that fcntl hangs.
 *
 * It tries to use fcntl() 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 test currently just hangs.
 *
 * Compile: gcc -Wall -o stc-flock-fork stc-flock-fork.c
 ***********************************************************************/

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/wait.h>
#include <sys/file.h>
#include <sys/mman.h>

#define NUM_TEST_ITERS 1
#define MAX_ITER 10
#define CHILDREN 3
#define MAX_COUNT (MAX_ITER * CHILDREN)

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

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

struct flock mutex_lock_it;
struct flock mutex_unlock_it;


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

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

        int rc;
        int i;
        for (i=0; i<MAX_ITER; ++i) {

            if (verbose)
                printf("Child %d: %d\n", childnum, i);

            /* Get the lock. */
            do {
                rc = fcntl(fd2, F_SETLKW, &mutex_lock_it);
            } while (rc < 0 && errno == EINTR);
            if (rc < 0) {
                perror("lock");
                exit(1);
            }
            
            /* Increment the counter. */
            *x = increment(*x);

            /* Release the lock. */
            do {
                rc = fcntl(fd2, F_SETLKW, &mutex_unlock_it);
            } 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 n;
    int fd;
    int i;
    int verbose = (argc > 1) ? 1 : 0;
 
    /* Create the temporary file. */
    fd = mkstemp(tmpfilename);
    if (fd < 0) {
        perror("open failed");
        exit(1);
    }
    close(fd);

    /* Initialize shared memory */
    init_shm();

    /* Setup mutexes */
    mutex_lock_it.l_whence = SEEK_SET;   /* from current point */
    mutex_lock_it.l_start = 0;           /* -"- */
    mutex_lock_it.l_len = 0;             /* until end of file */
    mutex_lock_it.l_type = F_WRLCK;      /* set exclusive/write lock */
    mutex_lock_it.l_pid = 0;             /* pid not actually interesting */
    mutex_unlock_it.l_whence = SEEK_SET; /* from current point */
    mutex_unlock_it.l_start = 0;         /* -"- */
    mutex_unlock_it.l_len = 0;           /* until end of file */
    mutex_unlock_it.l_type = F_UNLCK;    /* set exclusive/write lock */
    mutex_unlock_it.l_pid = 0;           /* pid not actually interesting */

    /* Perform the test multiple times. */
    for (i = 0; i < NUM_TEST_ITERS; ++i) {
        /* Create the children. */
        for (n = 0; n < CHILDREN; n++)
            make_child(n, verbose, 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;
}

--
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

Reply via email to