title: Strange line buffering behaviour in Tcl 8.6?
body: <p>EDIT: Original example and alternative solution framework modified for clarity.</p>
  
  <p>The line buffering behaviour might behave differently than expected in Tcl 8.6. The following code blocks without any output, unless the "chan close" line is uncommented:</p>
  
  <pre><code>set data {one two four}
  set stream [open |[list cat -n] r+]
  chan configure $stream -buffering line
  
  chan puts $stream "$data\n"
  chan puts $stream "\n"
  chan flush $stream
  #chan close $stream write
  set out [chan read $stream]
  puts "output: $out"
  chan close $stream
  </code></pre>
  
  <p>So this simplistic solution does not work for interactive I/O, and this might be related to synchronization problems at both ends of the pipe.</p>
  
  <p>Using a channel event structure (e.g., based on <a href="http://www.beedub.com/book/2nd/event.doc.html" rel="nofollow noreferrer">http://www.beedub.com/book/2nd/event.doc.html</a>), seems to be preferable:</p>
  
  <pre><code>proc chanReader { pipe } {
  
     global extState
  
     while 1 {
        set len [chan gets $pipe line]
        if { $len &gt; 0 } {
           puts "&lt;&lt; $line."
           continue
        } else {
           if { [chan blocked $pipe] } {
              set extState 1
              return
           } elseif { [chan eof $pipe] } {
              set extState 2
              return
           }
        }
     }
  }
  
  
  set data {one two foure}
  set timeout 5000
  
  #set stream [open [list | cat -n] r+]
  #set stream [open [list | ispell -a] r+]
  set stream [open [list | tr a-z A-Z] r+]
  #set stream [open [list | fmt -] r+]
  chan configure $stream -blocking 0 -buffering line
  set extState 0
  chan event $stream readable [list chanReader $stream]
  
  foreach word $data {
     puts "&gt; $word\n"
     chan puts $stream "$word\n"
     chan flush $stream
     #chan close $stream write
     set aID [after $timeout {set extState 3}]
     vwait extState
     if { $extState == 1 } {
        # Got regular output.
        after cancel $aID
        puts "Cancel $aID."
        continue
     } elseif { $extState == 2 } {
        puts "External program closed."
        chan close $stream
        exit 2
     } elseif { $extState == 3 } {
        puts "Timeout."
        chan close $stream
        exit 3
     }
  }
  
  puts "End of task."
  chan close $stream
  exit 0
  </code></pre>
  
  <p>This code fragment works with the "cat -n" and "ispell -a" external programs (commented lines), but still fails with other external programs. For instance it does not work with the "tr a-z A-Z" and "fmt" examples above.</p>
  
  <p>If the line "chan close $stream write" above is uncommented, we receive output from the external program, but this terminates the interaction with it. How to reliably connect (interactively) to these external programs?</p>