www.delorie.com/archives/browse.cgi   search  
Mail Archives: cygwin/2012/02/18/16:52:24

X-Recipient: archive-cygwin AT delorie DOT com
X-SWARE-Spam-Status: No, hits=-1.7 required=5.0 tests=AWL,BAYES_00,RCVD_IN_DNSWL_NONE,TW_FC
X-Spam-Check-By: sourceware.org
Message-ID: <4F401D73.7010908@acm.org>
Date: Sat, 18 Feb 2012 13:51:47 -0800
From: David Rothenberger <daveroth AT acm DOT org>
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:10.0.2) Gecko/20120216 Thunderbird/10.0.2
MIME-Version: 1.0
To: cygwin AT cygwin DOT com
Subject: Re: STC for libapr1 failure
References: <20120214182452 DOT GK25918 AT calimero DOT vinschen DOT de> <4F3AD58A DOT 9040106 AT acm DOT org> <20120215153851 DOT GQ25918 AT calimero DOT vinschen DOT de> <4F3C09D9 DOT 6000406 AT acm DOT org> <20120215204521 DOT GB27454 AT calimero DOT vinschen DOT de> <4F3C208B DOT 2060007 AT acm DOT org> <20120215212010 DOT GA4183 AT calimero DOT vinschen DOT de> <4F3C2E35 DOT 3080308 AT acm DOT org> <20120216140932 DOT GI19092 AT calimero DOT vinschen DOT de> <4F3D2748 DOT 8080205 AT acm DOT org> <20120216160458 DOT GK19092 AT calimero DOT vinschen DOT de>
In-Reply-To: <20120216160458.GK19092@calimero.vinschen.de>
X-IsSubscribed: yes
Reply-To: cygwin AT cygwin DOT com
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

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

On 2/16/2012 8:04 AM, Corinna Vinschen wrote:
> On Feb 16 07:56, David Rothenberger wrote:
>> On 2/16/2012 6:09 AM, Corinna Vinschen wrote:
>>> I read the Linux man page again (http://linux.die.net/man/2/flock)
>>> and I just hacked the following testcase, based on your flock STC.
>>
>> That sounds pretty close to what the APR test case is doing, as far as I
>> understand.
>>
>>> The testcase is attached.  I'm pretty curious what your test is actually
>>> testing.
>>
>> I got to work at my real job all last night, so couldn't extract the STC
>> from the APR test suite. But, here's the test in APR-ese in case you're
>> interested. I'll remove the APRisms as soon as I can to get you another
>> test case.

I've extracted the test case, which is attached.

I must humbly apologize. The test case was actually using fcntl() for
file locking, not flock(). I got thrown off by the name of the test:
"testflock". It seems APR prefers fcntl() for file locking if available.

The attached test works fine for me on Linux, but fails on Cygwin
starting with the 20120215 snapshot.


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

"So why don't you make like a tree, and get outta here."
                -- Biff in "Back to the Future"

--------------090003090902050204080406
Content-Type: text/plain;
 name="stc-fcntl-forkexec.c"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename="stc-fcntl-forkexec.c"

/***********************************************************************
 * This is a STC to show a process can get an exclusive lock on a file using
 * fcntl, even though another process has an exclusive lock.
 *
 * A parent process uses fcntl to get an exclusive lock. It then
 * uses fork/exec to spawn a child of itself, which also tries to get an
 * exclusive lock on the file.
 *
 * If all works correctly, the child should not be able to get the
 * lock. However, the child is able to get the lock.
 *
 * This test was extracted from the APR test suite.
 *
 * Compile: gcc -Wall -o stc-fcntl-forkexec stc-fcntl-forkexec.c
 ***********************************************************************/
#define _GNU_SOURCE
#include <sys/types.h>
#include <sys/file.h>
#include <sys/wait.h>

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

#define TESTFILE "testfile.lock"

error_t
lock_file (int fd, int cmd)
{
  int rc;
  struct flock l = { 0 };
  int fc;

  l.l_whence = SEEK_SET;  /* lock from current point */
  l.l_start = 0;          /* begin lock at this offset */
  l.l_len = 0;            /* lock to end of file */
  l.l_type = F_WRLCK;
  fc = cmd;

  /* keep trying if fcntl() gets interrupted (by a signal) */
  while ((rc = fcntl(fd, fc, &l)) < 0 && errno == EINTR)
    continue;

  if (rc == -1) {
    /* on some Unix boxes (e.g., Tru64), we get EACCES instead
     * of EAGAIN; we don't want APR_STATUS_IS_EAGAIN() matching EACCES
     * since that breaks other things, so fix up the retcode here
     */
    if (errno == EACCES) {
      return EAGAIN;
    }
    return errno;
  }
  return 0;
}

/* The child */
void
tryread ()
{
  int fd;
  error_t status;
  
  fd = open (TESTFILE, O_WRONLY, 0666);
  if (fd < 0)
    {
      perror ("child open failed");
      exit (2);
    }

  status = lock_file (fd, F_SETLK);
  if (status == 0)
    exit(0);
  if (status == EAGAIN)
    exit(1);
  exit(2);
}

int
main (int argc, const char *const *argv)
{
  int fd;
  const char *args[3];
  pid_t pid;
  pid_t pstatus;
  int exit_int;

  if (argc > 1)
    {
      /* Called to run the child. */
      tryread ();
      fprintf (stderr, "Should not get here!\n");
      return 2;
    }  

  /* Create the lock file. */
  fd = open (TESTFILE, O_WRONLY|O_CREAT, 0666);
  if (fd < 0)
    {
      perror ("open failed");
      return 1;
    }

  /* Lock the file. */
  if (lock_file (fd, F_SETLKW) != 0)
    {
      perror ("lock");
      return 1;
    }

  /* Spawn the child reader */
  if ((pid = fork ()) < 0)
    {
      perror ("fork");
      return 1;
    }
  else if (pid == 0) {
    /* child */
    args[0] = program_invocation_name;
    args[1] = "child";
    args[2] = NULL;
    execl (program_invocation_name, program_invocation_name, "child", NULL);
    fprintf (stderr, "execv failed\n");
    _exit (2);
  }

  /* Wait for the child. */
  do {
    pstatus = waitpid (pid, &exit_int, WUNTRACED);
  } while (pstatus < 0 && errno == EINTR);

  if (WIFEXITED (exit_int))
    {
      exit_int = WEXITSTATUS (exit_int);
      if (exit_int == 0)
        printf ("FAILED: Child was able to get a lock when it shouldn't.\n");
      else if (exit_int == 1)
        printf ("SUCCESS: Child was not able to get the lock.\n");
      else
        fprintf (stderr, "Unexpected error from child: %d\n", exit_int);
    }
  else
    fprintf (stderr, "Child did not terminate normally.\n");
  
  /* Close the file */
  close (fd);

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

  return 0;
}


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

- Raw text -


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