chan pending, a chan action, retrieves the about of data pending in a channel's buffer.
Returns the number of bytes in Tcl's buffers for the channel channelId in the direction specified by mode (which must be input or output).
chan pending makes it safe to use chan gets with sockets, which can now be inspected to detect an excessively long line, providing an opportunity to prevent memory exhaustion.
chan pending is designed for use with non-blocking channels, especially sockets, and it is used to deal with the case where the source is producing far more data than was expected before producing some particular delimiter, e.g., a newline character for gets.
proc accept {cb channel args} { global timeouts chan configure $channel -blocking 0 -buffersize 4096 chan event $channel readable [list doGets $channel $cb] set ::timeouts($channel) "" } proc doGets {channel callback} { global timeouts if {[chan gets $channel line] >= 0} { after cancel $timeouts($channel) set timeouts($channel) "" {*}$callback $channel $line } elseif {[chan eof $channel]} { chan close $channel after cancel $timeouts($channel) unset timeouts($channel) } else { # Must be blocked; check for excessive buffering if {[chan pending input $channel] > 1024} { # must be a line longer than a kilobyte; naughty! reject chan close $channel after cancel $timeouts($channel) unset timeouts($channel) } elseif {$timeouts($channel) eq ""} { # no line timeout watcher; install one that waits 10 seconds # from when the start of the line arrives to when the end of the # line arrives before killing the channel set timeouts($channel) [after 10000 killChannel $channel] } } } proc killChannel channel { global timeouts unset timeout($channel) chan close $channel } # Make the (server) socket socket -server [list accept processLineCallback] 12345 # This is where you'd add your code to handle each line proc processLineCallback {channel line} { # ... whatever ... puts $channel-->$line }