4

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                         
    ...
 }
pynexj
  • 19,215
  • 5
  • 38
  • 56
comatose
  • 1,952
  • 7
  • 26
  • 42
  • Can you clarify: Why does this need to go via threads? (What is the purpose -- are you going to do something with `$position` in another thread?) What do you mean "_not defined_" -- in another thread? – zdim May 09 '17 at 18:51
  • @zdim The reason that this needs to go via threads or another separate process is because I want the main process to do some other work which includes taking input from user and doing some other stuff, so I need that to be always responsive to inputs. That forces me to use a separate thread/process to do this periodic work with Expect. By $position not defined what I mean is that Expect fails to match the Password. It is not used by any other thread (basically its a kinit renew loop that provides password via Expect very periodic interval) – comatose May 09 '17 at 20:22
  • OK, thank you. So then you can nicely `fork` and be done with it, but the question remains of why `Expect` doesn't do its thing in a thread. – zdim May 09 '17 at 20:24

1 Answers1

1

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.

zdim
  • 64,580
  • 5
  • 52
  • 81