Solved

IPC::Open3 call is causing blocking, script is locking up, please help...

Posted on 2007-03-30
7
357 Views
Last Modified: 2012-06-27
Hello,

Will someone please help me...  I am totally stuck on this IPC::Open3 call thing, cause of blocking I believe.  My calls execute once through, but on the second attempt of the loop, the process hangs.  The results of waitpid are never returned...

      open (CATCHERR, "+>>error.txt")   || die $!;
      local *CATCHIN = IO::File->new_tmpfile;
      local *CATCHOUT = IO::File->new_tmpfile;

    my $pid = open3(">&CATCHIN",\*CATCHOUT, ">&CATCHERR", $cmd);

    waitpid ($pid, 0);
    if ($?) {
          print "That child exited with wait status of $?<br />\n";
      }

    while( <CATCHERR> ) { }

    while( <CATCHOUT> ) { }

      close (CATCHERR);
      close (CATCHOUT);
      close (CATCHIN);

      sleep(3);


I believe this has something to do with "blocking" which I've read about in perldoc, but don't know how to properly solve.  Can someone please explain what to do with my code so I can execute my command multiple times over and over again in loop with the program locking up on me?  How do I properly wait for it finish executing... getting a result code... without locking up the script?

Thanks in advance,
G
0
Comment
Question by:ghosting
  • 4
  • 3
7 Comments
 
LVL 84

Expert Comment

by:ozo
ID: 18826329
could $cd be waiting for input on CATCHIN, or could it have filled the buffer on CATCHOUT and be waiting for someone to read it?
0
 

Author Comment

by:ghosting
ID: 18826390
I am not sure...

Let's try and approach both possibilities.  First how do I read CATCHOUT so that it is no longer full?  I am guessing this is more than likely the culprit, as the program I am executing can generate a fair amount of output quickly.

Secondly, if it is CATCHIN that is waiting for some sort of flush to say that the $cmd input is done, how do I send that?  I have but one lengthy command ($cmd) that I am trying to execute on multiple network hosts in a loop that I am running, so how do I tell CATCHIN that input is done, and to flush it's contents to CATCHOUT and CATCHERR?

This has really been beating me up for a couple of days now.  Any quick help is most appreciated.

Thanks in advance,
G
0
 
LVL 84

Expert Comment

by:ozo
ID: 18826428
you can close(CATCHIN) to say that input is done, and
while( <CATCHOUT> ) { } to read CATCHOUT
but if you waitpid before doing any of that, you may be waiting for $pid while $pis is waiting for you
0
Threat Intelligence Starter Resources

Integrating threat intelligence can be challenging, and not all companies are ready. These resources can help you build awareness and prepare for defense.

 

Author Comment

by:ghosting
ID: 18826700
OK,

I've tried modifying my code a bit, with closing CATCHIN and reading CATCHOUT and CATCHERR.  I am still having problems...  the code runs through the loop once, outputting everything CATCHERR finds the first time no problem, BUT on the second loop through, it stops / hangs about 5 lines into CATCHERR.

      local *CATCHIN = IO::File->new_tmpfile;
      local *CATCHOUT = IO::File->new_tmpfile;
      local *CATCHERR = IO::File->new_tmpfile;

    my $pid = open3(">&CATCHIN", ">&CATCHOUT", \*CATCHERR, $cmd);

       close (CATCHIN);

    while( <CATCHOUT> ) {
            push (@output, $_);
          print "CATCHOUT = ".$_."<br />\n";
    }

    while( <CATCHERR> ) {
            push (@lineresults, $_);
          print "CATCHERR = ".$_."<br />\n";
          }

    waitpid ($pid, 0);
    if ($?) {
          print "That child exited with wait status of $?<br />\n";
      }

      close (CATCHERR);
      close (CATCHOUT);

      sleep(3);


If you could please help me properly read / close CATCHERR such that I can read the results, and not have it hang on the 5th line of returned results on the second loop... I would be a very happy camper.  This is killing me, I have been stuck on this problem for days and must have it solved today.

Thanks in advance,
G
0
 
LVL 84

Accepted Solution

by:
ozo earned 500 total points
ID: 18826773
Could you give me an example of a $cmd that produces this problem?
I tried this example, and it worked for me

$cmd = qq(perl -le 'print while <>; for(1..10){ print STDERR; print;} exit +(localtime)[0]');
use IO::File;
use IPC::Open3;
for( 1..5 ){
local *CATCHIN = IO::File->new_tmpfile;
local *CATCHOUT = IO::File->new_tmpfile;
local *CATCHERR = IO::File->new_tmpfile;

my $pid = open3(">&CATCHIN", ">&CATCHOUT", \*CATCHERR, $cmd);

close (CATCHIN);

while( <CATCHOUT> ) {
    push (@output, $_);
    print "CATCHOUT = ".$_."<br />\n";
}

while( <CATCHERR> ) {
    push (@lineresults, $_);
    print "CATCHERR = ".$_."<br />\n";
}

waitpid ($pid, 0);
if ($?) {
    print "That child exited with wait status of $?<br />\n";
}

close (CATCHERR);
close (CATCHOUT);

sleep(3);
}
0
 

Author Comment

by:ghosting
ID: 18826968
Sure...

Although, the command I am using is a bit complex, and that might be part of the problem.  However, I have checked the command from a DOS prompt and it executes no problems.  So in order to get started, download PsExec from SysInternals @ http://www.microsoft.com/technet/sysinternals/utilities/psexec.mspx

Once you've installed PsTools and added the PsTools directory to your system path, either at runtime or system wide, go ahead and try something along the lines of ....

$cmd = 'psexec \\\\remote_machine -u domain\\user_name -p password -n 45 -i -c -f "C:\\path_to_batch\\batch.bat"';

where batch.bat is a DOS batch file with something like

@echo off
copy \\host_machine\C$\path_to\md5sum.exe C:\
copy \\host_machine\C$\path_to\some_vbscript.vbs C:\
C:\some_vbscript.vbs
ping -n 3 127.0.0.1>nul
del D:\some_vbscript.vbs
del D:\md5sum.exe
exit

Basically the PsExec command will copy the DOS Batch file to the remote_machine, which will then execute the Batch file, copying over the needed VBScript and MD5sum files for my script, which get executed, then erased, and the program exits.  You can make the DOS Batch file do anything you want, but it should copy some files, execute them, then exit to be a fair test.

I have this all set up to run from a list of remote machines held in a file, changing the parameters for each target based on what I read in from my config files.  The program was working for a while until it got more complex and now it just hangs, rarely completing execution, which really sucks, considering this is a backup script designed for a large network.

I can't seem to figure out why it hangs, but any help on getting this run clean through without hanging would be most appreciated.  Thanks for taking the time to look into this with me.

Regards,
G
0
 

Author Comment

by:ghosting
ID: 19062398
OK,
I didn't acutal think anyone was going to try the example I posted, since it was more a bunch of pieces acting a one script.  I did get it working, as described in the example, but by changing psexec to not return a status code, but just a PID stating the process started.  

There is some sort of timeout error between waiting for psexec and stderr to connect and return on long execution times, more than a few seconds.  So that was my final solution that made everybody happy.

Thanks for all your input.
G
0

Featured Post

What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

Join & Write a Comment

Email validation in proper way is  very important validation required in any web pages. This code is self explainable except that Regular Expression which I used for pattern matching. I originally published as a thread on my website : http://www…
In the distant past (last year) I hacked together a little toy that would allow a couple of Manager types to query, preview, and extract data from a number of MongoDB instances, to their tool of choice: Excel (http://dilbert.com/strips/comic/2007-08…
Explain concepts important to validation of email addresses with regular expressions. Applies to most languages/tools that uses regular expressions. Consider email address RFCs: Look at HTML5 form input element (with type=email) regex pattern: T…
This video explains how to create simple products associated to Magento configurable product and offers fast way of their generation with Store Manager for Magento tool.

708 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now