require 5.00557; $DEBUG = 1; use Tk; sub FileHandle::flush { my ($self) = @_; my $ofh = select $self; my $ob = $|++; print $self ''; $| = $ob; select $ofh; } my $text = 'Click me to start'; pipe FROMCHILD, TOPARENT or die "pipe up: $!; aborting"; pipe FROMPARENT, TOCHILD or die "pipe down: $!; aborting"; for (\*FROMCHILD, \*TOCHILD, \*FROMPARENT, \*TOPARENT) { bless $_ => FileHandle; select $_; $|++; } select STDOUT; my $pid = fork; defined $pid or die "fork: $!; aborting"; if ($pid) { # parent close TOPARENT; close FROMPARENT; } else { close TOCHILD; close FROMCHILD; mainlooper(); exit; } while ("aaaaabbbbb" =~ /.(?{pause()})/g) { print "----\n"; } $DEBUG && print "PARENT: Exiting\n"; exit; sub pause { $DEBUG && print "PARENT: Pausing $` $& $'\n"; writestrs(\*TOCHILD, $`, $&, $'); pipewait(\*FROMCHILD); } sub mainlooper { my $mw = new Tk::MainWindow; $mw->Button(-textvar => \$text, -command => \&button)->pack; MainLoop; } sub button { $DEBUG && print "CHILD: In button callback\n"; my @text = readstrs(\*FROMPARENT); $text = join '/', @text; pipekick(\*TOPARENT); $DEBUG && print "CHILD: Returning to event loop.\n"; } sub writestrs { my $fh = shift; my $n = @_; $DEBUG && do { local $" = ')('; print "PARENT: Writing (@_)\n" }; print $fh $n, ':'; local $_; for (@_) { print $fh length($_), ':', $_; # print STDOUT length($_), ':', $_; } # $fh->flush; } sub readstrs { my $fh = shift; my $n = readnum($fh); $DEBUG && print "CHILD: Reading $n strings from pipe:\n"; my @strs; while ($n--) { my $len = readnum($fh); my $s; read $fh, $s, $len; $DEBUG && print "CHILD: Read $s\n"; push @strs, $s; } @strs; } sub readnum { my $n = ''; my $fh = shift; my $c; $DEBUG && print "CHILD: Reading number from pipe:\n"; while (($c = getc($fh)) ne ':' && $c ne '') { $n .= $c; } if ($c eq '') { $DEBUG && print "CHILD: Premature end of file on pipe; aborting\n"; exit; } $DEBUG && print "CHILD: Read number $n.\n"; $n; } sub pipewait { my $pipe = shift; my $s; $DEBUG && print "PARENT: Waiting for kick.\n"; sysread $pipe, $s, 1; $DEBUG && print "PARENT: Got the kick.\n"; } sub pipekick { my $pipe = shift; $DEBUG && print "CHILD: Kicking pipe.\n"; print $pipe "x"; $pipe->flush; }