On 19.07.2021 21:24, Rich wrote:
> An individual Tcl interpreter is single threaded. When the interpreter
> is running your Tcl code, it is not running the event loop.
> Conversely, the event loop only runs when your Tcl code is not running.
> So when you block in a [gets] call, you also block the event loop from
> being executed as well.
Okay.. now that part makes sense to me.
> You may have to handle gets returning to your code by signaling that
> only a "partial line" was available -- so you will likely need to make
> some code changes. Read the [gets] man page portions that address
> non-blocking mode.
I suspected it, but I don't fully get it, I am afraid. From the man page
(
http://tcl.tk/man/tcl8.6/TclCmd/gets.htm) I read:
"If channelId is in non-blocking mode and there is not a full line of
input available, the command returns an empty string and does not
consume any input. If varName is specified and an empty string is
returned in varName because of end-of-file or because of insufficient
data in non-blocking mode, then the return count is -1"
With non-blocking mode this means that [gets] returns -1 (with a varName
specified). But it returns -1 as well on EOF. To distinguish the cases,
I can use [eof] and [fblocked]. So far, so good.
But what can I do when [gets] doesn't get a full line of input and the
sock is [fblocked] consequently? Wait for more data to come? How can
this be achieved without blocking the event loop?
Actually the server is not under my control and I don't have any
influence on what it sends or when... I can only react. I could mock up
a server and test this case. But how to provoke it?
Actually the only way I can think of is something like this:
method connect {} {
set Sock [socket -async localhost 1234]
fconfigure $Sock -translation auto -buffering line -blocking 0
fileevent $Sock readable [list [self] handleSocket $Sock]
}
method handleSocket {sock} {
set message ""
try {
gets $sock message
if {![fblocked $sock]} {
# process message only when the sock is not blocked
my ProcessMsg $message
} elseif {[eof $sock]} {
close $sock
}
} trap {} {err status} {
puts "handleSocket raised Error: $err $status $message"
}
}
To process the message only if the socket is not blocked (in which case
it should be a complete line), and hope that it will be unblocked some when.
--
EL