Solved

eval

Posted on 2008-11-01
12
897 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
Netscaler Common Configuration How To guides

If you use NetScaler you will want to see these guides. The NetScaler How To Guides show administrators how to get NetScaler up and configured by providing instructions for common scenarios and some not so common ones.

 
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
 

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

What is SQL Server and how does it work?

The purpose of this paper is to provide you background on SQL Server. It’s your self-study guide for learning fundamentals. It includes both the history of SQL and its technical basics. Concepts and definitions will form the solid foundation of your future DBA expertise.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
crawling gofundme 4 127
Vb script to unzip a files and rename the files 5 92
Regex rule to match two different url 5 72
Matching a random pattern with one common character 2 64
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…
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…
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…

821 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