Package: libtcl8.6
Version: 8.6.2+dfsg-2+iwj1
Tags: + fixed-upstream
Control: fixed -1 8.6.5+dfsg-2

Running the attached script demonstrates that gets(3tcl) has a serious
bug in jessie's tcl.  See attached transcript.

I used gdb on tcl8.6 and the bug seems to be that in TclGetsObjBinary,
if CHANNEL_BLOCKED is set on entry, and the buffer does not already
contain a newline, TclGetsObjBinary doesn't attempt to read from the
underlying fd.  It simply indicates "nothing ready now".

The fd remains readable, so the fileevent re-triggers.

In a real application this means that the event loop will spin.  It
will not only use excessive CPU use, but this spinning can prevent
other events being processed, resulting in nonfunctional applications.

I found this bug report in the upstream bug tracker which seems
relevant:
  https://core.tcl.tk/tcl/tktview/10dc6daa375d45051a3c
Particularly, the comment "anonymous added on 2014-10-17 08:43:43"
contains a code change which looks to me like it would fix the
problem (although this code is very tangled).

A good approach for Debian might be to update stable's tcl8.6 to a
more recent upstream stable branch.  stretch's tcl8.6 does not have
the bug, and AFAICT is very similar to upstream 8.6.5.

Thanks,
Ian.

#!/usr/bin/tclsh8.6

file delete -force p
exec mkfifo -m 600 p

set writer [open p r+]
set reader [open p r]

fconfigure $reader -blocking false -translation binary
fconfigure $writer -buffering none

set counter 0

proc readable-gets {args} {
    global reader counter
    puts stderr readable
    set got [gets $reader l]
    puts stderr "readable got=$got l=$l"
    if {[incr counter] > 20} { puts stderr BUG; exit 1 }
}

proc do-write {s} {
    global writer
    puts stderr "writing `$s'"
    puts -nonewline $writer $s
}

proc do-read-read {n} {
    global reader
    puts stderr "reading-with-read n=$n"
    set got [read $reader $n]
    puts stderr "reading-with-read n=$n got=$got"
}

fileevent $reader readable readable-gets

#do-read-read 30

do-write "half a line"

after 1000 { do-write "half a line more" }
after 2000 { do-write "rest of the line\n" }
after 3000 { puts stderr OK; exit 0 }

vwait forever

-- 
Ian Jackson <[email protected]>   These opinions are my own.

If I emailed you from an address @fyvzl.net or @evade.org.uk, that is
a private address which bypasses my fierce spamfilter.
_______________________________________________
Pkg-tcltk-devel mailing list
[email protected]
http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/pkg-tcltk-devel

Reply via email to