Solved

eval

Posted on 2008-11-01
12
894 Views
Last Modified: 2012-05-05
the following script properly timesout in unix but not in windows OS  (both have perl 5.10)

eval
{
  $SIG{ALRM} = sub { die "timeout" } ;
  alarm 2;
  `perl -e "while (1) {}"`;
  alarm 0;
};
alarm 0;
if ($@)
{
  print "Error = $@";
}


However if i replace   `perl -e "while (1) {}"`;  with  sleep 10
then it works in windows. somehow it doesn't like when the command is executed with backticks  on windows
0
Comment
Question by:shahkinjal
  • 5
  • 3
  • 2
  • +2
12 Comments
 
LVL 43

Expert Comment

by:ravenpl
ID: 22860659
Yes, it looks like You right. Though I don't know why it happens so, I verified that using system() instead of backticks works.
0
 
LVL 6

Expert Comment

by:Talmash
ID: 22861197
Idles / timeouts are offtenly OS dependant.

use
if (OS == windows) {
  1st syntax
} else {
 2nd syntax
}

years ago, I used this dummy solution, without messing with couple of OS types

tal
0
 

Author Comment

by:shahkinjal
ID: 22862396
I tried the following (it timeout correctly if my cmd is perl -e sleep 10  but if my command is "perl -v", the output is directly printed to STDOUT . The variable $out is empty which i m printing in the end

$cmd = "perl -v";

eval
{
  $SIG{ALRM} = sub { die "timeout" } ;
  alarm 2;
   $rc = system ("$cmd") ;
   $out = <STDOUT>;

  alarm 0;
};
alarm 0;
if ($@)
{
  print "Error = $@";
}

print "OUT = $out";
0
 
LVL 43

Expert Comment

by:ravenpl
ID: 22862402
You cannot
 $out = <STDOUT>;
STDOUT will always give You EOF(it's output only) - that's why the variable is empty.
0
 

Author Comment

by:shahkinjal
ID: 22862464
so how can i timeout in windows at the same time return me output if the command does not times out
0
 
LVL 43

Expert Comment

by:ravenpl
ID: 22862476
I'm not following, but did You wanted

>   $rc = system ("$cmd") ;
>   $out = <STDOUT>;

   open(SUB, "$cmd |") ;
   $out = <SUB>;
   close(SUB);
0
Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

 

Author Comment

by:shahkinjal
ID: 22862481
This works fine. it return me output and code

$cmd = "perl -v";
eval
{
  $SIG{ALRM} = sub { die "timeout" } ;
  alarm 2;

  open OUT, "$cmd |" or die "$cmd $!";
  @output = <OUT>;
  close OUT;
  $status = $?;
  alarm 0;
};
alarm 0;
if ($@)
{
  print "Error = $@";
}

print "output = @output \n";
print "code = $status \n";



but this does not time out

$cmd = "perl -e sleep 15";

eval
{
  $SIG{ALRM} = sub { die "timeout" } ;
  alarm 2;

  open OUT, "$cmd |" or die "$cmd $!";
  @output = <OUT>;
  close OUT;
  $status = $?;
  alarm 0;
};
alarm 0;
if ($@)
{
  print "Error = $@";
}

print "output = @output \n";
print "code = $status \n";
0
 

Author Comment

by:shahkinjal
ID: 22862489
if alarm does not work is there any other alternative way to timeout on windows if the command is executed using backticks
0
 
LVL 39

Expert Comment

by:Adam314
ID: 22864015
Although I'm not certain, I'm guessing the alarm signal is going to the child, not your process.  You could try something like:

eval {
  my $start = time();
  my $output = '';
  open OUT, "$cmd |" or die "$cmd $!";
  local $/;
  while(<OUT>) {
    $output .= $_ ;
    die "Timeout\n" if (time() - $start > 2);
  }
  close OUT;
}

With this, you will only have the possibility of timing out whenever the program outputs some data.  So, if you ran "perl -e sleep 10", this would not timeout.  But if the program you want to timeout outputs some data regularly, this might work.

The other thing you could do is create a new child thread, and run the program in the child.  Then you could terminate that thread after the timeout.  I haven't tested this in windows though...
0
 
LVL 8

Expert Comment

by:jhurst
ID: 22872569
Windows is not a real operating system in may respects.  Perl simulates the aspects associated with threading as well as it can.  You have run afoul of that
0
 

Author Comment

by:shahkinjal
ID: 22873046
threads seems to work but 1 issue:

the following code properly timeout on WINDOWS but the problem is even the script is completed, the while loop is still running in the system background and i have to manually clean it. can i get the process id and kill it in the script itself?

use threads;

my $pid;
my $child_thread = threads->new(\&my_function);

eval
{
      local $SIG{ALRM} = sub { die "timeout" };
      alarm 5;
      while ( $child_thread->is_running() ) { sleep 1; }
      alarm 0;
};
alarm 0;
if ($@)
{   print "Timeout: $@ \n";
    $child_thread->kill('KILL')->detach();
}

sub my_function
{
   local $SIG{'KILL'} = sub { threads->exit(); };  
   `perl -e "while (1) {}"`;
}
0
 
LVL 39

Accepted Solution

by:
Adam314 earned 500 total points
ID: 22883081
If you use open with |, the return value will be the PID of the process.  With backticks, I don't think there is a way to get the PID.

So to get the PID:
    my $pid_of_new_process = open(my $P, "your_command goes here|");  #Don't forget the pipe at the end

What you'll have to be careful of is that if the command you run has shell meta-characters, perl will pass the command to the shell for processing, and the shell will then start the program.  So the $pid_of_new_process will be the PID of the shell, not your actual program.

0

Featured Post

6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

Join & Write a Comment

I've just discovered very important differences between Windows an Unix formats in Perl,at least 5.xx.. MOST IMPORTANT: Use Unix file format while saving Your script. otherwise it will have ^M s or smth likely weird in the EOL, Then DO NOT use m…
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…
In this seventh video of the Xpdf series, we discuss and demonstrate the PDFfonts utility, which lists all the fonts used in a PDF file. It does this via a command line interface, making it suitable for use in programs, scripts, batch files — any pl…

747 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

10 Experts available now in Live!

Get 1:1 Help Now