If you call interact
and there's no input ready right away, it mistakes that for EOF and closes the connection, which isn't what you want, in case more input can come along later.
Here's a fix:
--- a/exp_inter.c +++ b/exp_inter.c @@ -1433,7 +1433,7 @@ Exp_InteractObjCmd( switch (rc) { case EXP_DATA_NEW: cc = intRead(interp,u,1,0,key); - if (cc > 0) break; + if (cc > 0 || Tcl_InputBlocked(u->channel)) break; rc = EXP_EOF; /*
And here's a contrived way to expose it:
expect -c 'package require tcl::transform::core; oo::class create null {superclass tcl::transform::core; method read {c data} {};}; spawn cat /dev/zero; chan push $spawn_id [null new]; interact;'
I expected the above would run forever (there's no EOF in /dev/zero), and with the above fix it does. But currently version 5.45.3 exits (it gets EOF). What's going on is /dev/zero spews null bytes forever, causing interact
to call Tcl_ReadChars
, but the transformation (null
) discards all input, returning empty string. interact
should keep going: The the connection isn't EOF. There never will be any input, but that's different.
In blocking mode, Tcl_ReadChars
doesn't return until either 1) it consumes charsToRead
of input or 2) EOF (possibly after no input or less than charsToRead
of input). Or 3) an error. So in blocking mode, 0 <= ret < charsToRead
is always EOF. ret == -1
is in case of an error.
But in non-blocking mode (the case here) it returns after 1) charsToRead
of input, 2) EOF, 3) it would block, or 4) an error. Both 2) and 3) are possibly after no input or less than charsToRead
of input, so 0 <= ret < charsToRead
is either EOF or "would block waiting for more input". ret == -1
is in case of an error, still. The only way to distinguish 2) and 3) is with Tcl_Eof
and Tcl_InputBlocked
.
The actual case where I encountered this is with a channel transformation that strips ANSI escape sequences. (I need to either strip these sequences or add them to all of my interact
patterns, which is a major pain.) The transformation works great! unless a chunk of input contains nothing but escape sequences: Then it returns empty string and interact
summarily closes the connection :-P
Hi, thank you for the patch. I will try to create a release witht he fix during this weekend once I have verified it.
Awesome, thank you!
This is now fixed in the expect 5.45.4 release.
This is great, thanks again!