Subject: | IO::Pty: read from pty master sometimes hangs on OS X |
Date: | Sat, 12 Feb 2011 23:26:33 -0600 |
To: | bug-IO-Tty [...] rt.cpan.org |
From: | Jonathan Nieder <jrnieder [...] gmail.com> |
Hi,
A few days ago, Thomas Rast reported that one of git's tests[1]
that uses IO::Pty was getting stuck randomly (i.e., not every
run). Turns out this is reproducible without using git at all.
Reproduction recipe:
i=0
while ./demo.perl echo hi $i
do
: $((i = i + 1))
done
Expected result:
hi 0
hi 1
hi 2
hi 3
...
Actual result:
Stops after 2000 iterations or so.
Platform:
$ perl -V | head -4
Summary of my perl5 (revision 5 version 10 subversion 0) configuration:
Platform:
osname=darwin, osvers=10.0, archname=darwin-thread-multi-2level
uname='darwin neige.apple.com 10.0 darwin kernel version 10.0.0d8: tue may 5 19:29:59 pdt 2009; root:xnu-1437.2~2release_i386 i386 '
$ uname -rv
10.5.0 Darwin Kernel Version 10.5.0: Fri Nov 5 23:19:13 PDT 2010; root:xnu-1504.9.17~1/RELEASE_X86_64
Also reproducible with perl 5.8.9. demo.perl follows[2].
Ideas?
Jonathan
[1] http://thread.gmane.org/gmane.comp.version-control.git/166423
http://repo.or.cz/w/git.git/blob/v1.7.4:/t/t7006-pager.sh
[2] -- 8< --
#!/usr/bin/perl
use strict;
use warnings;
use IO::Pty;
my $master = new IO::Pty;
my $slave = $master->slave();
my $pid = fork;
if (not defined $pid) {
die "fork failed: $!";
} elsif ($pid == 0) { # child
close $master or die "child: cannot close master: $!";
open STDOUT, ">&", $slave or die "child: cannot dup2 slave: $!";
close $slave or die "child: cannot close slave: $!";
exec(@ARGV) or die "cannot exec $ARGV[0]: $!";
}
# parent
close $slave or die "parent: cannot close slave: $!";
while (1) {
my $nread = sysread($master, my $buf, 4096);
defined($nread) or $!{EIO} or die "cannot read from child: $!";
last if !$nread;
unless (syswrite(\*STDOUT, $buf, $nread) == $nread) {
die "cannot write: $!";
}
}
close $master or die "parent: cannot close master: $!";
my $waiting = waitpid($pid, 0);
die "waitpid failed: $!" if $waiting < 0;
exit($?);