From: Ean on
Hello - I've been chasing an odd problem where my expect scripts lose
stdout midway through execution. I've isolated it to the following
conditions:
1. the script is spawned in the background from a shell or other
script
2. the script has an expect with a 'timeout' in a nested proc

If I remove the timeout, the script runs normally. If I only use a
proc 1 level deep, the script runs normally. If I'm not in the
background, the script runs normally. I'm stumped, any ideas?

I'm running fedora core 10, expect 5.43.0.

the wrapper shell script:
#!/bin/sh
echo "starting"

test=`./test.exp > test.txt 2>&1 &`

tail -f -n 100 test.txt
----------------------------------------

The expect script:
#! /usr/bin/expect --

proc next_level {shellId} {
set timeout 10
send -i $shellId "ls -1\n"
expect {
timeout -i $shellId { puts "timed out\n" }
-i $shellId -re "\\\$"
}
puts "finished next_level"
return 0
}
proc do_it {} {
spawn bash
set shellId $spawn_id
expect -i $shellId -re "\\\$"

puts "spawned, going to next level"
set ret [next_level $shellId]
return $shellId
}

set shellId [do_it]
send -i $shellId "exit\n"
puts "exited"
---------------------------------------

As you can see from the debug output, expect reads eof...but why?!? :
...
expect: does " " (spawn_id exp4) match regular expression "\$"? no

expect: does "" (spawn_id exp0) match glob pattern "exp4"? no
expect: read eof
expect: set expect_out(spawn_id) "exp0"
expect: set expect_out(buffer) ""
error writing "stdout": bad file number
while executing
"puts "finished next_level""
...
-----------------------------------------------------
I've spent about 4 hours researching this, and have tried everything
that looked semi-relevant in the 'Background Processing' chapter of
'Exporing Expect', but no luck.

Any tips, pointers or suggestions would be greatly appreciated.
Ean
From: David Bariod on
On Sep 25, 2:08 am, Ean <scoobysna...(a)gmail.com> wrote:
> 2. the script has an expect with a 'timeout' in a nested proc
>
> If I remove the timeout, the script runs normally.

This is a hint.
Your timeout pattern is not correct.
I don't understand how it is related to your stdout issue,
but fixing this line makes your problem disappear.

> timeout -i $shellId { puts "timed out\n" }

the option should be befor ethe pattern:
-i $shellId timeout { puts "timed out\n" }
It should correct your problem.

David Bariod
From: Ean on
> This is a hint.
> Your timeout pattern is not correct.
> I don't understand how it is related to your stdout issue,
> but fixing this line makes your problem disappear.
>
> >                 timeout -i $shellId { puts "timed out\n" }
>
> the option should be befor ethe pattern:
> -i $shellId timeout { puts "timed out\n" }
> It should correct your problem.
>
> David Bariod

wow, thank you!! The legacy expect code base I'm working with
actually has no id's at all for the timeout values...I had inserted
the -i in an attempt to get it to work.

Looking at page 253 of 'Exploring Expect', it actually states:
Even though there is no -i flag preceding timeout, the pattern does
not associate with the currently spawned process. Timeouts do not
associate with processes.

Even more odd is that it would fail only with the exact combination of
factors.

Anyway, thanks again, you've saved me a considerable headache!
Ean