[comp.lang.perl] pty and/or shared FH bug

hakanson@ogicse.ogc.edu (Marion Hakanson) (12/13/89)

This is Perl-3.0, patchlevel 6.  Below I have a script which uses
pseudo-tty's to feed input to a program, and accept output back
from that program.  The example script uses "tr A-Z a-z" as the
program on the slave side of the pty, but you can imagine that a
more complicated program might be put there instead.

Here's the script, with the getpty.pl following at the end of this
message:

====================================
#!/usr/bin/perl

do 'getpty.pl';
die "$@, aborted" if $@;

$MAST = 'MASTER';
$SLAV = 'SLAVE';
($mast,$slav) = do getpty($MAST,$SLAV);
print STDERR "getpty returns '$mast','$slav'\n";
die 'Cannot get pty, aborted' if ($mast eq '');

if ( fork ) {			# parent
  close($SLAV);		# not needed


  if ( fork ) { 	# still parent
    open(MASTOUT, "+>&$MAST") || die "Cannot dup $MAST to MASTOUT, aborted";
    close($MAST);
    select(MASTOUT); $| = 1;
    select(STDOUT); $| = 1;

    for ($i=0; $i<10; $i++ ) {
      print MASTOUT "LINE out $i\n" || die "Cannot print to $mast, aborted";
      sleep(1);
    }
    exit(0);
  } else {		# child 2
    open(MASTIN, "+>&$MAST") || die "Cannot dup $MAST to MASTIN, aborted";
    close($MAST);

    while ($mastin = <MASTIN>) {
      print STDOUT "$$: $mastin";
    }
    exit(0);
  }
} else {				# child 1
  close($MAST);	# not needed

  open(STDOUT, "+>&$SLAV") || die "Cannot dup $SLAV to STDOUT, aborted";
  open(STDIN, "+>&$SLAV") || die "Cannot dup $SLAV to STDIN, aborted";
  close($SLAV);

  select(STDOUT); $| = 1;

  exec ('tr','A-Z','a-z') || die "Cannot start 'tr', aborted";
}
====================================

The script does just the right thing when run on both MtXinu-4.3bsd
(uVAX-II) and on DYNIX-3.0.12 (4.2bsd, Sequent S81), namely it prints
out the following, with nice 1-second intervals between each line.

getpty returns '/dev/ptyp0','/dev/ttyp0'
12481: line out 0
12481: line out 1
12481: line out 2
12481: line out 3
12481: line out 4
12481: line out 5
12481: line out 6
12481: line out 7
12481: line out 8
12481: line out 9

But under SunOS-4.0.3 (Sun-3), everything which gets put into the
master side, also comes out unchanged, in addition to the output
of the "tr" program, again with 1-second intervals between each
pair of output lines:

getpty returns '/dev/ptyp2','/dev/ttyp2'
1963: LINE out 0
1963: line out 0
1963: LINE out 1
1963: line out 1
1963: LINE out 2
1963: line out 2
1963: LINE out 3
1963: line out 3
1963: LINE out 4
1963: line out 4
1963: LINE out 5
1963: line out 5
1963: LINE out 6
1963: line out 6
1963: LINE out 7
1963: line out 7
1963: LINE out 8
1963: line out 8
1963: LINE out 9
1963: line out 9

So, the question is, is this a SunOS bug, or a Perl bug with how it
interacts with SunOS?  A pty bug, a stdio bug, or a Perl-shared-FH
bug?  How about a workaround?

Larry: It's looking more and more to me like you should think about
packaging up a PD stdio package with Perl, in the same manner as the
regexp package.  Or build Perl I/O on top of file descriptors, instead
of file pointers, so when you fork you don't get all those shared
pointers, etc.  In case you couldn't tell, I've had a bit of trouble
with forked filehandles lately, although in this case I've rearranged
the order of forks in various permutations, all with the same results.

====================================
sub getpty {

  local ($MASTER,$SLAVE) = @_;
  local ($master,$slave);
  
  $master = '';
  $slave = '';

  pty: while ( </dev/pty*> ) {
#    print STDERR "trying '$_'\n";
    $master = $_;
    unless ( open($MASTER,"+>$master") ) {
#      print STDERR "open failed: $master\n";
      $master = '';
      next pty;
    }
    
    s/pty/tty/;
    $slave = $_;
    last pty if ( open($SLAVE,"+>$slave") );

#    print STDERR "open failed: $slave\n";
    close($MASTER);
    $master = '';
    $slave = '';
  }

#  print STDERR "getpty returning '$master','$slave'\n";

  ($master,$slave);
}
====================================

-- 
Marion Hakanson         Domain: hakanson@cse.ogi.edu
                        UUCP  : {hp-pcd,tektronix}!ogicse!hakanson