Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

comment on

( [id://3333]=superdoc: print w/replies, xml ) Need Help??

I am trying to write a reusable object oriented class for using IPC::Open3 module.
I have couple of problems in dealing with File handles. Can you guys review the code and suggest where it is going wrong or how it can be better ?

Issues need to resolve
-----------------------
1)Want to check whether input filehandle is ready to receive input(current WNOHANG is not helpful when command supplied runs for long time)
2)Issues with output and error file handles in returning buffer text.

cmd.pl -------------- use Task; my $obj = Task->new("cat","-t"); my $obj = Task->new("sleep 50"); $obj->start(); if($obj->canSendInput) { print $obj->sendInput("Practical Extraction Report Language\n" +, "Visual C plus plus"); } print "\noutput1:" . $obj->getOutput(); print "\nError:" . $obj->getError(); print "\n"; $obj->stop(); print $obj->sendInput("Second Input"); [thiagu@host1 ~/exe_abs]$ ./cmd.pl Filehandle GEN0 opened only for output at Task.pm line 89. Use of uninitialized value in concatenation (.) or string at Task.pm l +ine 118. 1 Filehandle GEN0 opened only for output at Task.pm line 89. output1: Error: Task.pm ---------------- package Task; use strict; use warnings; use IPC::Open3; use IO::Select; use IO::Handle; use POSIX qw(:sys_wait_h); #Creating Object sub new { my($class, $cmd, @args) = @_; return bless({ cmd => $cmd, args => \@args, pid => undef, stdout => "", stderr => "", }, $class); } #Running the command with arguments supplied and opening file handles +for inout, output and error sub start { my $self = shift; my $cmd_to_exe = "$self->{cmd} "."@{$self->{args}}"; # Reading both output and error filehandles sametime $self->{'selector'} = IO::Select->new(); $self->{inputfh} = IO::Handle->new(); $self->{outputfh} = IO::Handle->new(); $self->{errorfh} = IO::Handle->new(); { $self->{pid} = open3($self->{inputfh}, $self->{outputfh}, $sel +f->{errorfh}, $cmd_to_exe); $self->{'selector'}->add($self->{inputfh}, $self->{outputfh}, +$self->{errorfh} ); #print $self->{pid}; return (1); } } sub canSendInput { my $self = shift; my $pid = waitpid($self->{pid}, WNOHANG); #print $pid; #return $pid; ($pid==0)?return(1):return(0); } #Sending input to command by printing in the input file handler sub sendInput { my $self = shift; my @input = @_; if(canSendInput($self)) { my $kid = waitpid($self->{pid}, WNOHANG); foreach my $input(@input) { (print {$self->{inputfh}} "$input") or return (0); return (1); } } } #Retriving output of the command executed for the last input sub getOutput { my $self = shift; my $errCall = shift; my $outputfh = $self->{outputfh}; my $errorfh = $self->{errorfh}; my $output = ""; my $error = ""; my @ready = $self->{selector}->can_read(1); foreach my $fh ( @ready ) { while(sysread($fh, my $text, 1024)) + #Reading 1024 bytes in every iteration { if(fileno($fh) == fileno($outputfh)) { $output.= $text; #print $text; last if(length($text) < 1024); } else { $error.= $text; #print $text; last if(length($text) < 1024); } } } #Returning only Error when getOutput is called from getError() and sav +ing output text into object so we can use it later if($errCall) { $self->{stdout} = $output; $error.=$self->{stderr}; # Updating errors which are not returne +d so far $self->{stderr} = ""; return $error; } #Returning only Output when getOutput is called directly after saving +error text into object so we can use it later else{ $self->{stderr} = $error; $output.=$self->{output}; # Updating output which are not returne +d so far $self->{stdout}=""; return $output; } } #Retriving error sub getError { my $self = shift; my $error = getOutput($self, 1); return $error; } sub stop { my $self = shift; if( defined( $self->{'selector'} ) ) { $self->{'selector'}->remove( $self->{inputfh}, $self->{outputf +h}, $self->{errorfh} ); } local $SIG{INT} = 'IGNORE'; kill INT => -$$; } #Destructor sub DESTROY { my $self = shift; &stop; } 1;

Thanks, Thiagu


In reply to Queries on open3 by thiagu_mvt

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.
  • Log In?
    Username:
    Password:

    What's my password?
    Create A New User
    Domain Nodelet?
    Chatterbox?
    and the web crawler heard nothing...

    How do I use this?Last hourOther CB clients
    Other Users?
    Others taking refuge in the Monastery: (4)
    As of 2024-07-16 07:06 GMT
    Sections?
    Information?
    Find Nodes?
    Leftovers?
      Voting Booth?

      No recent polls found

      Notices?
      erzuuli‥ 🛈The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.