'''`[chan] pending`''', a `[chan]` action, retrieves the about of data pending in a [channel]'s buffer. ** Synopsis ** : '''chan pending''' ''mode channelId'' ** Documentation ** [TIP] [http://www.tcl.tk/cgi-bin/tct/tip/287%|%287]: resulted in `chan pending` ** Description ** 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 [socket]s, which can now be inspected to detect an excessively long line, providing an opportunity to prevent memory exhaustion. ** How to Use ** `chan pending` is designed for use with non-blocking channels, especially [socket]s, 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 } ====== <> Command | Channel