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

#!/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();