Spawn Expect from a perl thread

556 Views Asked by At

I am working on a script which needs to spawn an Expect process periodically (every 5 mins) to do some work. Below is the code that I have that spawns an Expect process and does some work. The main process of the script is doing some other work at all times, for example it may wait for user input, because of that I am calling this function 'spawn_expect' in a thread that keeps calling it every 5 minutes, but the issue is that the Expect is not working as expected.

If however I replace the thread with another process, that is if I fork and let one process take care of spawning Expect and the other process does the main work of the script (for example waiting at a prompt) then Expect works fine.

My question is that is it possible to have a thread spawn Expect process ? do I have to resort to using a process to do this work ? Thanks !

sub spawn_expect {
    my $expect = Expect->spawn($release_config{kinit_exec});
    my $position = $expect->expect(10,
                    [qr/Password.*: /, sub {my $fh = shift; print $fh "password\n";}],
                    [timeout => sub {print "Timed out";}]);
    # if this function is run via a process, $position is defined, if it is run via a thread, it is not defined                         
    ...
 }
1

There are 1 best solutions below

0
On

Create the Expect object beforehand (not inside a thread) and pass it to a thread

my $exp = Expect->spawn( ... );
$exp->raw_pty(1);
$exp->log_stdout(0);

my ($thr) = threads->create(\&login, $exp);
my @res = $thr->join();    
# ...

sub login {
    my $exp = shift;
    my $position = $exp->expect( ... );
    # ...
}

I tested with multiple threads, where one uses Expect with a custom test script and returns the script's output to the main thread. Let me know if I should post these (short) programs.

When the Expect object is created inside a thread it fails for me, too. My guess is that in that case it can't set up its pty the way it does that normally.

Given the clarification in a comment I'd use fork for the job though.