1

Let me ask the question with a specific set of example. The 1st code, nlines.pl is as follows:

#!/usr/local/bin/perl
#########################
# print Hello world n times with n entered by a prompt
#########################

use strict;
use Time::HiRes qw(sleep);

die "Syntax: $0 <prompt> <time2sleep>\n" if ($#ARGV < 1);
my $prompt = $ARGV[0] . '> ';
my $sleepsec = $ARGV[1];        print "$0: Timeout interval: $sleepsec\n";
print $prompt;
while (<STDIN>) {
        chomp;
        last unless /\d+/;
        my $loopCount = $_;
        print "\n$0: Received request for $loopCount lines\n";
        for (my $count = 0; $count != $loopCount ; $count++) {
                Time::HiRes::sleep($sleepsec) if ($sleepsec > 0);
                print "$0 [$count] Hello world\n"
        }
        print $prompt
}
print "Bye bye\n";
exit 0;

$ nlines.pl pp 0.2 generates a prompt "pp> ", and when given an input "6", prints "Hello world" 6 times, with 0.2 secs time intervals (only if the interval is +ve number). A non-numeric input gets you out of the loop, and a negative number for line count results in an infinite loop. Works fine!

Now, consider the 2nd script - "expnlines.pl", as a driver for the script above.

#!/usr/local/bin/perl
#############################
# expnlines.pl: driver for nlines.pl
#############################

use strict;
use Expect;

die "Syntax: $0 <Count> <SleepSec>\n" if ($#ARGV < 1);
my $count = $ARGV[0];
my $child = 'nlines.pl';
my $prompt = 'CountOfLines';
my $ex = Expect->new;
$ex->raw_pty(1);
$ex->spawn ($child, $prompt, $ARGV[1]);
$ex->expect (1, $prompt) or die "$0: No prompt from $child\n";
print "$0: Sending $count\n";
$ex->send($count . "\n");
$ex->expect (2, $prompt) or die "\n$0: Expect timed out for $count\n";
print "\n$0: Received prompt back from expect\n";
exit 0;

If we run this as "expnlines.pl 4 0.2" it works fine. "expnlines.pl -1 0.3" (or whatever else for the timeout) works too. For the -ve # for linecount, the 1st script enters into the infinite loop but is timed out by expect. However, "expnlines.pl -1 0" cannot stop the infinite loop (after those 2 seconds), and I cannot figure out how to get expect to interrupt this loop.

Any suggestions? TIA.

Btw, in my real world, I do not have any control over equivalent of the binary for "nlines.pl". My script is "expnlines.pl", and I am using expect as a driver for the binary, with different arguments. When the child process runs an infinite loop, I need some mechanism to detect and stop it, and I cannot figure out how. Appreciate the responses.

pynexj
  • 19,215
  • 5
  • 38
  • 56
Manidip Sengupta
  • 3,573
  • 5
  • 25
  • 27

1 Answers1

1

After a timeout you can close the command with a hard_close, (or a soft_close if you need to be nice, and can wait the extra time it uses), to terminate it, and the infinite loop.

Instead of

$ex->expect (2, $prompt) or die "\n$0: Expect timed out for $count\n";

You can do something like

if (!$ex->expect(2, $prompt)) {
    print "\n$0: Expect timed out for $count, closing\n";
    $ex->hard_close();
}
else {
    print "\n$0: Received prompt back from expect\n";
}
bolav
  • 6,938
  • 2
  • 18
  • 42
  • Tried your change, does not work for me. The problem - we never get to your 2nd line. Wondering if this is due to the OS, Perl/Expect versions, etc. I am on OSX El Capitan v10.11.3, Perl 5.22.1, Expect 1.320.0_0. If the solution works for you, do you mind sharing your platform and/or versions. Thank you. – Manidip Sengupta Mar 17 '16 at 17:29
  • OSX 10.10.5, Perl 5.20.1 and Expect 1.32. This works for me. – bolav Mar 17 '16 at 22:04