my $childThread = threads->new( \&Your::Package::childThreadWrite, $self, $l_cqrdMessage); #### lock $self->{waitFlag}; #### print do{ no strict 'refs'; \*( $self->{ inst } } }, $l_cqrdMessage; #### #! perl -slw use strict; package test; use threads qw[ yield ]; use threads::shared; use IPC::Open2; use constant TIMEOUT => 10; # seconds sub new { my( $class, $inst ) = @_; my $pid = open2( '>&STDOUT', do{ no strict 'refs'; \*{ $inst } }, 'perl58', '-e" print q[etx:], scalar <> for 1 .. 5; sleep 60; print q[Dying]; "' ) or die "Opening pipe failed: $!"; my %self : shared = ( inst => $inst, procID => $pid, ); return bless \%self, shift; } sub write { my( $self, $msg ) = @_; my $flag : shared = 1; warn 'Setting timeout'; my $timeout = time + TIMEOUT; my $thread = threads->create( \&tWrite, $self, \$flag, do{ no strict 'refs'; \*{ $self->{ inst } } }, $msg ); warn 'Waiting for flg to clear or timeout'; yield while do{ lock( $flag ); $flag } and time < $timeout; if( $flag ) { warn "Timeout; killing process:$self->{ procID }"; kill 9, $self->{ procID } or warn $!; warn 'Closing pipe'; close do{ no strict 'refs'; \*{ $self->{ inst } } } or warn "Close pipe failed: $!"; @{ $self }{ qw[ procID timeout ] } = ( undef, 0 ); warn 'Waiting for thread to notice'; $thread->join; warn 'Returning failure'; return 0; } warn 'Wrote successfully; waiting for thread to join'; $thread->join; warn 'joined'; return 1; } sub tWrite { my( $self, $flagref, $GLOB, $msg ) = @_; warn 'Writing'; print { $GLOB } $msg or warn "pipe: $!"; warn 'Written; clearing flag'; { lock( $$flagref ); $$flagref = 0; } warn 'Ending'; } sub done { my( $self ) = @_; close do{ no strict 'refs'; \*{ $self->{ inst } } } or warn $!; kill 9, $self->{ ProcID }; undef $self; } 1; package main; select do{ local $_ = select( STDERR ); $|++; $_ }; # Pass in a name to be used symbolically # for this instance pipe handle. my $test = test->new( 'PIPE' ); for (1 .. 10) { printf 'Enter to print a line of data'; ; warn 'Calling write'; unless( $test->write( 'X' x 1024 ) ) { warn 'Restarting external process'; $test->done; # Use the same name when we recreate the instance. $test = test->new( 'PIPE' ); } else { warn "Successfully wrote line $_"; } } warn 'Done'; exit;