This is the mail archive of the cygwin mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: flock still buggy


Corinna Vinschen <corinna-cygwin <at> cygwin.com> writes:

> 
> Do you have a working C testcase to demonstrate this?

I still haven't gotten around to trying your patch, but here is the testcase 
I'm using (I guess it's not that simple, after all):

$ cat foo.c
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/file.h>
#include <unistd.h>

int
main (int argc, char** argv)
{
  int mode, fd, pid;
  if (argc < 2)
    {
      printf ("usage: %s mode\n", argv[0]);
      printf ("  grab flock, fork, then sleep in parent and child\n");
      printf ("  mode can be a bitwise-or of:\n");
      printf ("    0 - no extra actions\n");
      printf ("    1 - mark fd as close-on-exec\n");
      printf ("    2 - close fd after fork\n");
      printf ("    4 - unlock in child\n");
      printf ("    8 - exec in child\n");
      return 1;
    }
  mode = atoi (argv[1]);
  fd = open ("bar", O_RDWR | O_CREAT, 0660);
  pid = getpid ();
  if (fd < 0)
    {
      printf ("open failed %d\n", errno);
      return 1;
    }
  printf ("%s pid %d starting\n", argv[0], pid);
  if ((mode & 1) == 1)
    {
      if (fcntl (fd, F_SETFD, FD_CLOEXEC | fcntl (fd, F_GETFD)) == -1)
        {
          printf ("%s pid %d fcntl failed %d\n", argv[0], pid, errno);
          return 1;
        }
      printf ("%s pid %d protected fd\n", argv[0], pid);
    }
  if (flock (fd, LOCK_EX))
    {
      printf ("%s pid %d failed to lock %d\n", argv[0], pid, errno);
      return 1;
    }
  printf ("%s pid %d got lock\n", argv[0], pid);
  if (fork ())
    {
      /* parent */
      if ((mode & 2) == 2)
        {
          if (close (fd))
            {
              printf ("%s pid %d close failed %d\n", argv[0], pid, errno);
              return 1;
            }
          printf ("%s pid %d closed\n", argv[0], pid);
        }
      sleep (10);
      printf ("%s pid %d exiting\n", argv[0], pid);
      return 0;
    }
  /* child */
  printf ("%s pid %d forked from %d\n", argv[0], (int) getpid (), pid);
  pid = getpid ();
  if ((mode & 4) == 4)
    {
      if (flock (fd, LOCK_UN))
        {
          printf ("%s pid %d unlock failed %d\n", argv[0], pid, errno);
          return 1;
        }
      printf ("%s pid %d unlocked\n", argv[0], pid);
    }
  if ((mode & 8) == 8)
    {
      printf ("%s pid %d execing\n", argv[0], pid);
      execlp ("sh", argv[0], "-c", "sleep 8; echo $0 pid $$ exiting",
              NULL);
      printf ("%s pid %d exec failed %d\n", argv[0], pid, errno);
      return 1;
    }
  sleep (8);
  printf ("%s pid %d exiting\n", argv[0], pid);
  return 0;
}


For an example of some of the bugs (which I hope your latest patch attempt 
fixes):

$ ./foo 4& sleep 2; ./foo 0
[1] 21692
./foo pid 21692 starting
./foo pid 21692 got lock
./foo pid 21704 forked from 21692
./foo pid 21704 unlocked
./foo pid 14060 starting
./foo pid 14060 got lock
./foo pid 21216 forked from 14060
./foo pid 21704 exiting
./foo pid 21692 exiting
./foo pid 21216 exiting
./foo pid 14060 exiting
[1]+  Done                    ./foo 4

Oops - process 14060 got the lock before 12692 and 21704 exited.

$ ./foo 15
$ ./foo 15
./foo pid 10932 starting
./foo pid 10932 protected fd
./foo pid 10932 got lock
./foo pid 10932 closed
./foo pid 26264 forked from 10932
./foo pid 26264 unlocked
./foo pid 26264 execing
./foo pid 26264 exiting
./foo pid 10932 exiting

Oops - process 26264 successfully unlocked fd, even though it was marked close-
on-exec by 10932 before the fork.

Now, on to try your patch...

-- 
Eric Blake



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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]