Tcl Library Source Code

View Ticket
Bounty program for improvements to Tcl and certain Tcl packages.
Ticket UUID: 1975182bddc84f6601f60b0acf2f326eae10316
Title: tcl::chan::cat - syntax error and bad behavior with fileevents
Type: Bug Version: 1.19
Submitter: anonymous Created on: 2019-03-12 23:15:43
Subsystem: tcl :: chan :: * Assigned To: aku
Priority: 5 Medium Severity: Critical
Status: Closed Last Modified: 2019-04-15 19:23:34
Resolution: Accepted Closed By: aku
    Closed on: 2019-04-15 19:23:34
tcl::cache::cat 1.0.3 has a critical bug, if an event handler has been registered on the reflected channel. 

By running the following code (interactively from wish)

package tcl::chan::chan
package tcl::chan::string

  # setup 2 simple data-channels.
  #  Here we use two simple string-channels but we could also [open] two simple files. 
set fd1 [tcl::chan::string "ABCDE..XYZ"]
set fd2 [tcl::chan::string "0123456789"]
 # setup a cat'enated channel
set ch [tcl::chan::cat $fd1 $fd2]

 # register a file handler printing the contents of the cat'enated channel
 #  by reading 4 bytes at time -- NOTE: ch is a global variable
# expected result is
# <<ABCD>>
# <<E..X>>
# <<YZ01>>
# <<2345>>
# <<6789>>
# <<>>
chan event $ch readable {
    if { [eof $ch] } { close $ch } else { puts "<<[read $ch 4]>>" }

# ! NOTHING happens !!!!

 # trying to force a read ...
read $ch 1 ;#  -->  error ... see below
bad event name "rc7": must be readable or writable

There's an error in the logic of the "watch" method.

I included a zip with all the updated files; corrections and some code cleaning.
- cat.tcl       --  the main correction, and version changed to 1.0.3
- pkgIndex.tcl  --  version changed 
-       --  version changed
- changeLog     --  version changed

User Comments: aku added on 2019-04-15 19:23:34:

Done with commit [aeb3bec0da].

Accepted with slight changes: - Comment tweaking, and - Restoring the early bailout in `read` when no channels to handle. - Added test suite for tcl::chan::cat.

It seems that just changing `fileevent` to `chan event` does the trick. And I am completely boggled why. These should have been equivalent. And they are not. I confirmed, I added a test case based on the given example, and the `vwait` used as event loop is stuck without the change, exactly as described.