Link to home
Start Free TrialLog in
Avatar of shahkinjal
shahkinjal

asked on

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
Avatar of ravenpl
ravenpl
Flag of Poland image

Yes, it looks like You right. Though I don't know why it happens so, I verified that using system() instead of backticks works.
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
Avatar of shahkinjal
shahkinjal

ASKER

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

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

   open(SUB, "$cmd |") ;
   $out = <SUB>;
   close(SUB);
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";
if alarm does not work is there any other alternative way to timeout on windows if the command is executed using backticks
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...
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
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) {}"`;
}
ASKER CERTIFIED SOLUTION
Avatar of Adam314
Adam314

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial