public inbox for cygwin@cygwin.com
 help / color / mirror / Atom feed
From: Corinna Vinschen <corinna-cygwin@cygwin.com>
To: cygwin@cygwin.com
Subject: Re: STC for libapr1 failure
Date: Thu, 16 Feb 2012 14:11:00 -0000	[thread overview]
Message-ID: <20120216140932.GI19092@calimero.vinschen.de> (raw)
In-Reply-To: <4F3C2E35.3080308@acm.org>

[-- Attachment #1: Type: text/plain, Size: 2743 bytes --]

On Feb 15 14:14, David Rothenberger wrote:
> On 2/15/2012 1:20 PM, Corinna Vinschen wrote:
> > On Feb 15 13:15, David Rothenberger wrote:
> >> On 2/15/2012 12:45 PM, Corinna Vinschen wrote:
> >>> On Feb 15 11:39, David Rothenberger wrote:
> >>>> But... now one of the flock tests is failing. It takes a while to
> >>>> extract a STC from the APR test suite because everything is written in
> >>>> APR-ese and I have to convert every APR call into the base C library
> >>>> calls. I'll work on that over the next day or three.
> >>>>
> >>>> The gist of the test that's failing is this:
> >>>>
> >>>>  * Create a file.
> >>>>  * Get an exclusive flock on it.
> >>>>  * Spawn a child process that attempts to get an exclusive, non-blocking
> >>>>    lock on the file.
> >>>>
> >>>> The test is expecting that the child will not be able to get the lock,
> >>>> but the child is able to.
> >>>[...]
> >>> Does it fork/exec or does it only exec? 
> >>
> >> Looks like fork/exec. execv to be precise.
> >>
> >>> I guess I really need the testcase.
> >> [...]

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.

It creates a lock in the parent, then forks a child.  The child tries to
grab the lock, first using the inherited file descriptor.  This is
supposed to work.  Then it opens the file again and tries to lock the
file using that descriptor.  This is supposed to fail with EWOULDBLOCK.
If it failed to lock the file one way or the other, it tries to unlock
the file using the second descriptor.  In theory this should fail.  If
it doesn't fail, it tries to lock the file again using both descriptors.
The expected result is the same as in the first two tries.  Eventually
the child exec's, and runs the entire set of tests again.  The result
should be the same as for the forked child.

I tried this test on both, Linux and Cygwin (latest from CVS), and it
behaves identically:

Linux$ ./stc-flock-forkexec
funlock from forked child with new descriptor succeeded but shouldn't
funlock from execed child with new descriptor succeeded but shouldn't

Cygwin$ ./stc-flock-forkexec
funlock from forked child with new descriptor succeeded but shouldn't
funlock from execed child with new descriptor succeeded but shouldn't

Funny enough, unlocking always returns success on the descriptor not
holding the lock, even on Linux.  But the second set of tests shows that
the lock is still firm in the hands of the first descriptor.

The testcase is attached.  I'm pretty curious what your test is actually
testing.


Corinna

-- 
Corinna Vinschen                  Please, send mails regarding Cygwin to
Cygwin Project Co-Leader          cygwin AT cygwin DOT com
Red Hat

[-- Attachment #2: stc-flock-forkexec.c --]
[-- Type: text/plain, Size: 3214 bytes --]

#define _GNU_SOURCE
#include <sys/types.h>
#include <sys/file.h>
#include <sys/wait.h>
#include <sys/mman.h>
#include <sys/stat.h>

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

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

void
test_child (int fd, const char *type, const char *fname)
{
  int rc;

  /* First try to lock using fd. */
  do
    {
      rc = flock (fd, LOCK_EX | LOCK_NB);
    }
  while (rc < 0 && errno == EINTR);
  if (rc < 0)
    fprintf (stderr, "flock from %s child with same descriptor: %s\n", type, strerror (errno));

  int fd2 = open (fname, O_RDONLY);
  if (fd2 < 0)
    perror ("child open");
  else
    {
      /* Try another descriptor. */
      do
	{
	  rc = flock (fd2, LOCK_EX | LOCK_NB);
	}
      while (rc < 0 && errno == EINTR);
      if (rc == 0)
	fprintf (stderr, "flock from %s child with new descriptor succeeded but shouldn't\n", type);
      else if (errno != EWOULDBLOCK)
	  fprintf (stderr, "flock from %s child with new descriptor: %s\n", type, strerror (errno));
      if (rc < 0)
	{
	  do
	    {
	      rc = flock (fd2, LOCK_UN);
	    }
	  while (rc < 0 && errno == EINTR);
	  if (rc == 0)
	    {
	      fprintf (stderr, "funlock from %s child with new descriptor succeeded but shouldn't\n", type);
	      do
		{
		  rc = flock (fd2, LOCK_EX | LOCK_NB);
		}
	      while (rc < 0 && errno == EINTR);
	      if (rc == 0)
		fprintf (stderr, "flock from %s child with new descriptor succeeded but shouldn't\n", type);
	      else if (errno != EWOULDBLOCK)
		  fprintf (stderr, "flock from %s child with new descriptor: %s\n", type, strerror (errno));
	      do
		{
		  rc = flock (fd, LOCK_EX | LOCK_NB);
		}
	      while (rc < 0 && errno == EINTR);
	      if (rc < 0)
		fprintf (stderr, "flock from %s child with same descriptor: %s\n", type, strerror (errno));
	    }
	}
      close (fd2);
    }
}

/* Fork and use flock to lock and unlock the file repeatedly in the child. */
void
make_child (int fd, pid_t * pid)
{
  if ((*pid = fork ()) < 0)
    {
      perror ("fork failed");
      exit (1);
    }
  else if (*pid == 0)
    {
      char buf[32];

      test_child (fd, "forked", tmpfilename);
      snprintf (buf, 32, "%d", fd);
      execl (program_invocation_name, program_invocation_name, buf, tmpfilename, NULL);
      perror ("execl");
      exit (1);
    }
}

/* 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);
}

int
main (int argc, const char *const *argv)
{
  pid_t child;
  int rc;
  int fd;

  if (argc > 1)
    {
      test_child (atoi (argv[1]), "execed", argv[2]);
      exit (0);
    }

  /* Create the temporary file. */
  fd = mkstemp (tmpfilename);
  if (fd < 0)
    {
      perror ("open failed");
      exit (1);
    }
  do
    {
      rc = flock (fd, LOCK_EX);
    }
  while (rc < 0 && errno == EINTR);
  if (rc < 0)
    {
      perror ("lock");
      exit (1);
    }

  make_child (fd, &child);

  await_child (child);

  close (fd);

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

  return 0;
}


[-- Attachment #3: Type: text/plain, Size: 218 bytes --]

--
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	other threads:[~2012-02-16 14:11 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-02-14  8:00 David Rothenberger
2012-02-14  8:07 ` David Rothenberger
2012-02-14 14:03 ` Corinna Vinschen
2012-02-14 14:46   ` Corinna Vinschen
2012-02-14 17:58     ` David Rothenberger
2012-02-14 18:25       ` Corinna Vinschen
2012-02-14 21:43         ` David Rothenberger
2012-02-15 15:39           ` Corinna Vinschen
2012-02-15 19:39             ` David Rothenberger
2012-02-15 20:46               ` Corinna Vinschen
2012-02-15 21:16                 ` David Rothenberger
2012-02-15 21:20                   ` Corinna Vinschen
2012-02-15 22:14                     ` David Rothenberger
2012-02-16 14:11                       ` Corinna Vinschen [this message]
2012-02-16 15:57                         ` David Rothenberger
2012-02-16 16:06                           ` Corinna Vinschen
2012-02-18 21:52                             ` David Rothenberger
2012-02-20 14:19                               ` Corinna Vinschen
2012-02-20 20:15                                 ` David Rothenberger
2012-02-21  1:29                                 ` Yaakov (Cygwin/X)
2012-02-21  8:59                                   ` Corinna Vinschen
2012-02-21 17:10                                     ` Corinna Vinschen
2012-02-23 14:20                                       ` Corinna Vinschen
2012-02-23 18:43                                         ` Achim Gratz
2012-02-24  3:49                                         ` Yaakov (Cygwin/X)
2012-02-24  8:15                                           ` Corinna Vinschen
  -- strict thread matches above, loose matches on Subject: below --
2011-08-26  0:39 David Rothenberger
2011-08-26 11:16 ` Corinna Vinschen
2011-08-27 20:37   ` Corinna Vinschen
2011-08-27 22:27     ` David Rothenberger
2011-08-29 13:55       ` Corinna Vinschen
2011-08-29 17:09         ` David Rothenberger

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20120216140932.GI19092@calimero.vinschen.de \
    --to=corinna-cygwin@cygwin.com \
    --cc=cygwin@cygwin.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).