You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
137 lines
3.4 KiB
137 lines
3.4 KiB
#!/usr/bin/perl |
|
use strict; |
|
use warnings; |
|
use Time::HiRes qw(usleep); |
|
use IPC::Open3; |
|
use IO::Handle; |
|
|
|
# ANSI color codes |
|
my $RESET = "\e[0m"; |
|
my $GREEN = "\e[32m"; # Child color |
|
my $YELLOW = "\e[33m"; # Parent color |
|
|
|
# Usage function |
|
sub usage { |
|
my ($args) = @_; |
|
print STDERR "rcvd : $0 $args\n"; |
|
print STDERR "usage:\n"; |
|
print STDERR " $0 pump <persecond> <maxcount>\n"; |
|
print STDERR " $0 parent\n"; |
|
print STDERR " $0 child <delay_ms>\n"; |
|
print STDERR "\n"; |
|
print STDERR "e.g:\n"; |
|
print STDERR " perl $0 pump 35 50 | perl $0 parent\n"; |
|
exit 1; |
|
} |
|
|
|
# Pump role |
|
sub pump { |
|
my ($persecond, $maxcount) = @_; |
|
if ($persecond > 1000) { |
|
print STDERR "WARNING: (>1000) sub millisecond scheduling not available - will go full speed\n"; |
|
usleep(500_000); |
|
} |
|
|
|
STDOUT->autoflush(1); |
|
STDERR->autoflush(1); |
|
|
|
my $counter = -1; |
|
my $ms = int(1000 / $persecond); |
|
|
|
while ($maxcount <= 0 || $counter < $maxcount - 1) { |
|
$counter++; |
|
print ".${counter}"; |
|
usleep($ms * 1000); |
|
} |
|
|
|
print STDERR "pump-done\n"; |
|
} |
|
|
|
# Parent role |
|
sub parent { |
|
print STDERR "${YELLOW}parent${RESET}\n"; |
|
usleep(250_000); |
|
|
|
# Read the first chunk from stdin |
|
my $parent_chunk1; |
|
read(STDIN, $parent_chunk1, 8); |
|
print STDERR "${YELLOW}${parent_chunk1}${RESET}\n"; |
|
|
|
# Launch the child process |
|
#my $child_pid = open3("<&STDIN", my $child_out, ">&STDERR", "perl", $0, "child", "150"); |
|
open(local *CHILD_STDIN, "<&", \*STDIN) or die "Can't dup STDIN: $!"; |
|
open(local *CHILD_STDERR, "<&", \*STDERR) or die "Can't dup STDERR: $!"; |
|
my $child_pid = open3("<&CHILD_STDIN", my $child_out, ">&CHILD_STDERR", "perl", $0, "child", "150"); |
|
|
|
binmode($child_out, ":utf8"); |
|
|
|
# Handle output from the child process asynchronously |
|
while (my $line = <$child_out>) { |
|
print STDERR $line; |
|
} |
|
#close $child_out; |
|
|
|
waitpid($child_pid, 0); |
|
|
|
print STDERR "parent-tail-read\n"; |
|
while (my $chunk = <STDIN>) { |
|
print STDOUT $chunk; |
|
} |
|
|
|
print STDERR "\n${YELLOW}parent-done${RESET}\n"; |
|
} |
|
|
|
# Child role |
|
sub child { |
|
my ($delay_ms) = @_; |
|
print STDERR "\n${GREEN}child${RESET}\n"; |
|
usleep($delay_ms * 1000); |
|
|
|
# Read exactly 16 characters from stdin |
|
my $chunk; |
|
my $bytes_read = read(STDIN, $chunk, 16); |
|
if (defined $bytes_read) { |
|
if ($bytes_read > 0) { |
|
print STDERR "${GREEN}child-read: $bytes_read bytes${RESET}\n"; |
|
} else { |
|
print STDERR "${GREEN}child-read: no data read${RESET}\n"; |
|
exit 0; |
|
} |
|
} |
|
print STDOUT "${GREEN}${chunk}${RESET}\n"; |
|
|
|
print STDERR "child-done\n"; |
|
exit 0; |
|
} |
|
|
|
# Main function |
|
sub main { |
|
my @args = @ARGV; |
|
if (@args < 1) { |
|
usage(""); |
|
} |
|
|
|
my $role = shift @args; |
|
if ($role eq "pump") { |
|
if (@args != 2) { |
|
usage("pump"); |
|
} |
|
my ($persecond, $maxcount) = @args; |
|
pump($persecond, $maxcount); |
|
} elsif ($role eq "parent") { |
|
if (@args != 0) { |
|
usage("parent"); |
|
} |
|
parent(); |
|
} elsif ($role eq "child") { |
|
if (@args != 1) { |
|
usage("child"); |
|
} |
|
my ($delay_ms) = @args; |
|
child($delay_ms); |
|
} else { |
|
usage($role); |
|
} |
|
} |
|
|
|
main(); |