eval

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
shahkinjalAsked:
Who is Participating?
 
Adam314Connect With a Mentor Commented:
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
 
ravenplCommented:
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
 
TalmashCommented:
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
Cloud Class® Course: Ruby Fundamentals

This course will introduce you to Ruby, as well as teach you about classes, methods, variables, data structures, loops, enumerable methods, and finishing touches.

 
shahkinjalAuthor Commented:
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
 
ravenplCommented:
You cannot
 $out = <STDOUT>;
STDOUT will always give You EOF(it's output only) - that's why the variable is empty.
0
 
shahkinjalAuthor Commented:
so how can i timeout in windows at the same time return me output if the command does not times out
0
 
ravenplCommented:
I'm not following, but did You wanted

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

   open(SUB, "$cmd |") ;
   $out = <SUB>;
   close(SUB);
0
 
shahkinjalAuthor Commented:
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
 
shahkinjalAuthor Commented:
if alarm does not work is there any other alternative way to timeout on windows if the command is executed using backticks
0
 
Adam314Commented:
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
 
jhurstCommented:
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
 
shahkinjalAuthor Commented:
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
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.