Menu

#17 Flushing doesn't work on stacked channel

open
nobody
None
5
2007-08-31
2007-08-31
No

Appears that [flush] command doesn't work properly if a transformation is attached to a socket.

If you run attached script as
./trftest.tcl server
(it opens a socket and waits for a client to connect),

and then run
./trftest.tcl
(it connects to the running server and reads from the socket)

you'll get nothing. Removing zip transformations or replacing [flush] by [unstack] or [close] makes test program working (it leaks sockets but it doesn't matter).

Other transformations works the same (I tried bz2, base64).

Discussion

  • Sergei Golovan

    Sergei Golovan - 2007-08-31
     
  • Andreas Kupries

    Andreas Kupries - 2007-10-12

    Logged In: YES
    user_id=75003
    Originator: NO

    Ok. I had the time to look at this due to a bug which had to be fixed in the zip stuff.
    It looks bleak. The problem is missing support in the core itself.

    (1) Channel drivers can have a flushProc, it is in the Tcl_ChannelType structure.
    (2) No driver actually implements this callback function, this includes Trf.
    (3) Because: The core is not actually using it. More blunt, there is no place
    in the Tcl core actually calling the flushProc in any way, shape, or form.

    The "flush" tcl command is implemented in Tcl_FlushObjCmd -> Tcl_Flush -> FlushChannel, and the last function simply takes whatever is in the Tcl output buffers and runs it through the channels -> outputProc, i.e. the driver function to write data to the OS.

    This means that channel drivers have no way of distinguishing whether a write was because of a user 'flush', a flush triggered by the IO system upon seeing a line, buffer full, or always (-buffering line, full, none). They simply see a series of write requests, nothing else.

    The transformations, which are just special drivers, have the same problem. for them it is more obvious, as for them it can make sense to actually do something special when the user triggers a flush (like for zip to Z_SYNC_FLUSH and force output, for a complete message for example).

    :(

    Going forward I would say that we should move the discussion to Tcl core and see what others with a stake in the core have to say about this.

    Thinking about it core support should actually be easy ... In FlushChannel look at the channel's flags. If CHANEL_CLOSED is set do nothing special. Ditto for BUFFER_READY. These two cases are for flush on close and internal flush by i/o system.

    Otherwise call the flushProc just before the outputProc. Semantics would be "The next write is special, a flush". The driver can remember that, handle accordingly in the output proc, and clear the flag ... No, that is not good. When multiple buffers wait each is flushed separately, for zip this means the message is littered with z_sync_flush'es. ... Alternative would be to call once before the output loop, and once after. Set/Reset the flush flag. At reset time the transformation can do its z_sync_flush.

    Comments ?