package CM::SOAPQueue; use base qw( Utils::Thread::JobQueue ); use strict; use warnings; use threads; use threads::shared; use FindBin qw( $Bin ); use autouse 'Carp' => qw( carp croak ); use autouse 'Data::Dumper' => qw( Dumper ); use autouse 'Memoize' => qw( memoize ); use autouse 'Pod::Usage' => qw( pod2usage ); use Time::HiRes qw( gettimeofday tv_interval ); use IO::All; use IO::Select; use POSIX qw( tmpnam :errno_h ); use Utils::Thread::Arg; use Sys::SigAction qw( set_sig_handler ); ############################################################ my $external_program = "$Bin/singleSOAPCall.pl"; ############################################################ sub init { my ($self) = @_; $self->WorkerSub( \&worker ); return $self; } sub worker { my ($arg_string) = @_; my $results; my $alarm = 0; my $h = set_sig_handler( 'ALRM', sub { $alarm = 1; }, {safe => 1} ); my $start = [gettimeofday]; my $arg = Utils::Thread::Arg::decode($arg_string); my $tmp_file = tmpnam; $arg->Input > io($tmp_file); # print STDERR $arg->Input; my $command_line = "$external_program --xml=$tmp_file"; print "Starting soap thread_id:" . threads->self->tid . " of arg:" . $arg->ID . "\n" if $::verbose > 4; my $pid; #timeout a system call: eval { alarm(2); # will force a timeout my $pid = open( COMMAND, "$command_line 2>&1 |" ) or die "Couldn't launch $command_line: $!\n"; threads->yield; my $select = IO::Select->new(*COMMAND); SELECT_LOOP: while (1) { if ( $select->can_read ) { READ_LOOP: while () { next READ_LOOP if /^\s*$/; $results .= $_; } last SELECT_LOOP; } ## end if ( $select->can_read) threads->yield; } ## end while (1) $select->remove(*COMMAND); close(COMMAND); alarm(0); }; #signal handler is reset when $h goes out of scope alarm(0); if ($@ or $alarm) { print "Timeout!\n"; # we timed out } if ( defined $pid ) { if ( kill 0 => $pid ) { # it is alive kill -9 => $pid; } elsif ( $! == EPERM ) { # changed uid } elsif ( $! == ESRCH ) { # is deceased, or zombie } else { # odd, couldn't check on status } } ## end if ( defined $pid ) my $duration = tv_interval( $start, [gettimeofday] ); unlink($tmp_file) or die "Unable to unlink $tmp_file\n"; $arg->Duration( $arg->Duration() + $duration ); print "SOAP took $duration on thread_id:" . threads->self->tid . " of arg:" . $arg->ID . "\n" if $::verbose > 4; $arg->Output($results); return Utils::Thread::Arg::encode($arg); } ## end sub worker 1;