CygPerl hangs opening FIFO after fork (in both parentchild)

2006-06-22 Thread Linda Walsh

The attached test case is simple and fairly short.  It does not
depend on File::BOM (and has none of the code from it).

It's only dependency (other than perl) is the POSIX module,
where, from, the fifo command is taken.

Conceptually, it is simple:

- Create fifo (works)
- Fork(works)
- Open fifo for communication between parent and child  (FAILS)

   (if successful, try to pass a short message, from child to
   parent, parent validates, then both processes exit)
-
   Both the child and the parent hang on the open.

Fork by itself works. 
Fifo communication, by itself, works.


Is this a simple enough test case?
Linda


#!/usr/bin/perl -w
use strict;
use POSIX qw( mkfifo );

my $message = EOM;
Hello, World.
That is all
EOM

my $testno=1;
#unbuffer outputs
select STDERR; $|=1; select STDOUT; $|=1;

sub check {
my ($stat,$msg)[EMAIL PROTECTED];
printf Test $testno had status %s;%s\n, 
$stat?pass:fail, 
$msg?(msg=$msg):;
++$testno;
return $stat;
}


my $fifo = 'test_fifo';
unlink $fifo if (-e $fifo); #prior hang?: 
cleanup



check( mkfifo($fifo, 0700), Created fifo $fifo ) or warn $!;

my $pid = fork;
if ($pid) {

check( 1 ,parent: forked ok, about to open fifo);
open my $reader, '', $fifo or die $$: Couldn't read '$fifo': $!;


 cygwin never gets here


check( 1, parent: after open about to read from child);
my $child_msg = $reader;

check ( ($child_msg eq $message) ,
parent: received msg from child, closing reader...);
close $reader;

check( 1 ,parent: closed reader, about to wait on child);
check( (waitpid($pid,0)  0), waitpid($pid)  0);

check(unlink($fifo), removed $fifo) or warn $!;

} elsif (defined $pid) {

check( 1, child: fork ok, about to open fifo);
open my $writer, '', $fifo or die $$: Couldn't write '$fifo': $!;

 cygwin never gets here

check (1, child: after opening fifo for write; about to print);
print $writer $message;

# diag $$: Wrote , length $message,  bytes to fifo;
check (1, child: wrote; about to close);  
close $writer;

check (1, child: closed; about to exit);
exit 0;

} else {
die $0: fork failed: $!;
}
--
Unsubscribe info:  http://cygwin.com/ml/#unsubscribe-simple
Problem reports:   http://cygwin.com/problems.html
Documentation: http://cygwin.com/docs.html
FAQ:   http://cygwin.com/faq/

Re: CygPerl hangs opening FIFO after fork (in both parentchild)

2006-06-22 Thread Brian Dessent
Linda Walsh wrote:

 The attached test case is simple and fairly short.  It does not
 depend on File::BOM (and has none of the code from it).
 
 It's only dependency (other than perl) is the POSIX module,
 where, from, the fifo command is taken.

This appears to be a deadlock in the Cygwin DLL when both the reader and
writer end of a fifo tries to open the file at the same time (or nearly
the same time.)  They end up signaling each other to ask about the other
end of the pipe, and hang there.  It has nothing to do with perl or
fork, as far as I can tell -- the attached C testcase will work fine if
the reader end sleeps briefly to ensure the opening order.   It's just a
classic race condition somewhere.

Brian#include stdio.h
#include string.h
#include stdlib.h
#include unistd.h
#include fcntl.h
#include sys/stat.h
#include sys/wait.h

#define FIFO_FILENAME test_fifo
#define ERROR_EXIT(x) { perror(x); exit (EXIT_FAILURE); }

int main (int argc, char **argv)
{
  int fd;
  pid_t pid;

  unlink (FIFO_FILENAME);
  
  if (mkfifo (FIFO_FILENAME, 0700) == -1)
ERROR_EXIT (mkfifo);

  if ((pid = fork ())  0)
{
  printf (parent: I am %d, child is %d\n, getpid (), pid);
  
  if (argc  1)
{
  puts (parent: sleeping);
  sleep (1);
}
  
  puts (parent: opening fifo);
  if ((fd = open (FIFO_FILENAME, O_RDONLY)) == -1)
ERROR_EXIT (parent open);
  
  puts (parent: closing fifo);
  close (fd);

  puts (parent: waiting for child);
  if (waitpid (pid, NULL, 0) != pid)
ERROR_EXIT (parent waitpid);
  
  puts (parent: removing fifo);
  if (unlink (FIFO_FILENAME) != 0)
ERROR_EXIT (parent unlink);

  puts (parent: exiting);
  exit (EXIT_SUCCESS);
 
}
  else if (pid == 0)
{
  puts (child: opening fifo);
  if ((fd = open (FIFO_FILENAME, O_WRONLY)) == -1)
ERROR_EXIT (child open);
  
  puts (child: closing fifo);
  close (fd);

  puts (child: exiting);
  exit (EXIT_SUCCESS);
}
  else
ERROR_EXIT (fork);
}

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

Re: CygPerl hangs opening FIFO after fork (in both parentchild)

2006-06-22 Thread Christopher Faylor
On Thu, Jun 22, 2006 at 06:53:38PM -0700, Brian Dessent wrote:
Linda Walsh wrote:

 The attached test case is simple and fairly short.  It does not
 depend on File::BOM (and has none of the code from it).
 
 It's only dependency (other than perl) is the POSIX module,
 where, from, the fifo command is taken.

This appears to be a deadlock in the Cygwin DLL when both the reader and
writer end of a fifo tries to open the file at the same time (or nearly
the same time.)  They end up signaling each other to ask about the other
end of the pipe, and hang there.  It has nothing to do with perl or
fork, as far as I can tell -- the attached C testcase will work fine if
the reader end sleeps briefly to ensure the opening order.   It's just a
classic race condition somewhere.

Yep.  It's a deadlock which uncovered a race.

It should be fixed in the next floor wax available at:

http://cygwin.com/snapshots/

And thanks for the test case which illustrated the problem.

cgf

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



Re: CygPerl hangs opening FIFO after fork (in both parentchild)

2006-06-22 Thread Yitzchak Scott-Thoennes
On Thu, Jun 22, 2006 at 06:53:38PM -0700, Brian Dessent wrote:
 Linda Walsh wrote:
 
  The attached test case is simple and fairly short.  It does not
  depend on File::BOM (and has none of the code from it).
  
  It's only dependency (other than perl) is the POSIX module,
  where, from, the fifo command is taken.
 
 This appears to be a deadlock in the Cygwin DLL when both the reader and
 writer end of a fifo tries to open the file at the same time (or nearly
 the same time.)  They end up signaling each other to ask about the other
 end of the pipe, and hang there.  It has nothing to do with perl or
 fork, as far as I can tell -- the attached C testcase will work fine if
 the reader end sleeps briefly to ensure the opening order.   It's just a
 classic race condition somewhere.

Good job isolating this problem, Linda and Brian.

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



Re: CygPerl hangs opening FIFO after fork (in both parentchild)

2006-06-22 Thread Christopher Faylor
On Thu, Jun 22, 2006 at 07:52:37PM -0700, Yitzchak Scott-Thoennes wrote:
On Thu, Jun 22, 2006 at 06:53:38PM -0700, Brian Dessent wrote:
 Linda Walsh wrote:
The attached test case is simple and fairly short.  It does not depend
on File::BOM (and has none of the code from it).

It's only dependency (other than perl) is the POSIX module, where,
from, the fifo command is taken.

This appears to be a deadlock in the Cygwin DLL when both the reader
and writer end of a fifo tries to open the file at the same time (or
nearly the same time.) They end up signaling each other to ask about
the other end of the pipe, and hang there.  It has nothing to do with
perl or fork, as far as I can tell -- the attached C testcase will work
fine if the reader end sleeps briefly to ensure the opening order.
It's just a classic race condition somewhere.

Good job isolating this problem, Linda and Brian.

Not to denigrate Brian's analysis but, AFAICT, there was already a
snapshot with the fix by the time he sent his mail.

I only point this out because I didn't want it to look like I was
ungrateful for Brian's analysis or that I used it and didn't give
credit.

cgf

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