Menu

#22 interact mistakes Tcl_InputBlocked for EOF

None
closed-fixed
nobody
None
5
2018-02-04
2018-01-29
Jack Bates
No

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

1 Attachments

Discussion

  • Nils Carlson

    Nils Carlson - 2018-02-03

    Hi, thank you for the patch. I will try to create a release witht he fix during this weekend once I have verified it.

     
  • Jack Bates

    Jack Bates - 2018-02-03

    Awesome, thank you!

     
  • Nils Carlson

    Nils Carlson - 2018-02-04

    This is now fixed in the expect 5.45.4 release.

     
  • Nils Carlson

    Nils Carlson - 2018-02-04
    • status: open --> closed-fixed
    • Group: -->
     
  • Jack Bates

    Jack Bates - 2018-02-04

    This is great, thanks again!

     

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.