Menu

#2124 Channels CloseProc() not called on close

obsolete: 8.4.1
open-remind
5
2003-10-16
2002-12-13
No

If there is pending BG output for a non-blocking channel
then Tcl_DriverCloseProc() is not called when the 'close'
command is invoked.

That can be seen from generic/tclIO.c :
Tcl_Unregister_Channel():
if (!(statePtr->flags & BG_FLUSH_SCHEDULED)) {
...

This can be very bad if channel's output is stalled, e.g. a
serial port blocked by handshake:

% puts "Tcl $tcl_patchLevel"
Tcl 8.4b1
% set chan [open com1: r+]
fileaaf550
% fconfigure $chan -buffering none -blocking 0
% fconfigure $chan -mode 1200,n,8,1 -handshake rtscts
% ### 2 outputs: "hello world" \x0D\x0A, BG_FLUSH
% puts $chan "hello world"
% puts "Queue: [fconfigure $chan -queue]"
Queue: 0 13
% after 1000
% puts "Queue: [fconfigure $chan -queue]"
Queue: 0 13
% close $chan
% set chan [open com1: r+]
couldn't open "com1:": permission denied
%

This problem occurs also for slow output without
handshake:

% puts "Tcl $tcl_patchLevel"
Tcl 8.4b1
% set chan [open com1: r+]
fileaaf768
% fconfigure $chan -buffering none -blocking 0
% # Explicitely reset handshake=none
% fconfigure $chan -mode 1200,n,8,1 -handshake none
% puts $chan "hello world"
% puts $chan "hello world"
% close $chan
% set chan [open com1: r+]
couldn't open "com1:": permission denied

For Tcl < 8.4. this has never been observed for serial
ports, because serial output has already been blocking.

Discussion

  • Rolf Schroedter

    Rolf Schroedter - 2002-12-13

    Logged In: YES
    user_id=99573

    This bahaviour may be interpretet not as a bug,
    but as a feature of the channel system.

    But then we need an additional option
    [fconfigure $chan -flushonclose 0]
    (default=1) for channels like serial ports.

     
  • Donal K. Fellows

    Logged In: YES
    user_id=79902

    When I have time (maybe, just maybe, over Xmas) I'll be
    advancing a TIP on behaviour-on-close of serial channels.

     
  • Don Porter

    Don Porter - 2002-12-13

    Logged In: YES
    user_id=80530

    Is this related to FR 525783 ?

     
  • Rolf Schroedter

    Rolf Schroedter - 2002-12-13

    Logged In: YES
    user_id=99573

    IMO not. [ 526163 ] tty not reset on exit
    is related to the (requested) change made by TIP#35, not to
    restore the original TTY settings on close, so that tcl can
    be used as a simple
    'stty' substitute.
    This stuff is not yet finally removed - see the comment in
    tclUnixChan.c, ttyCloseProc().

     
  • Andreas Kupries

    Andreas Kupries - 2003-01-06

    Logged In: YES
    user_id=75003

    Note: If BG_FLUSH_SCHEDULED is set the channel cannot
    be closed completely. There is a BackGround-FLUSH of data
    active. The channel won't be visible at the script level
    anymore, but the data structures remain until the flush is
    completed. After that happend the close proc is called and
    the structures are cleaned up completely. This is only for a
    non-blocking channel.

    To get 'flushonclose' behaviour just set the channel to -
    blocking 1. Of course, this may stall the [close] at the tcl
    level if the serial port itself is stalled.

     
  • Rolf Schroedter

    Rolf Schroedter - 2003-01-07

    Logged In: YES
    user_id=99573

    Yes, what you say emphasizes that Tcl needs a mechanism
    to close a stalled serial channel by discarding all currently
    pending output.

     
  • Donal K. Fellows

    Logged In: YES
    user_id=79902

    There are several possible desired behaviours for what
    should happen on closing of a serial channel, but I think
    these are the interesting cases:
    wait until all OS buffers are empty and reset to initial
    state
    discard all pending output (including OS level) and reset
    to init.
    leave channel in *current* state
    (I'll not specify what happens to the OS buffers in that
    last case as I believe that typically in that case, there
    won't be much data in the buffers anyway!)

    IIRC, right now we just support the first of those, and we
    know that selection of the right behaviour can't be done
    automatically (we don't want to discard debug info!) so that
    calls for a suitable [fconfigure] option. Which means a TIP.
    Which I've not had time to write. (And I'm not certain how
    -blocking interacts with this; the buffers in question are
    in the OS, not Tcl.)

     
  • Rolf Schroedter

    Rolf Schroedter - 2003-01-08

    Logged In: YES
    user_id=99573

    For blocking channels no changes are necessary.
    For non-blocking channels the current behaviour is to put the
    channel to *blocking* mode, wait until all Tcl output buffers
    are done and only then call Tcl_DriverCloseProc().

    If there would be a non-default [fconfigure -discardonclose 1]
    option the channel system should
    1. *Not* make the channel blocking.
    2. Discard all pending output in Tcl buffers.
    3. Immediately call Tcl_DriverCloseProc().

    The serial SerialCloseProc() is responsive for the OS-level
    output. So SerialCloseProc() should also check for the
    [fconfigure -discardonclose 1] flag and discard OS-level output.

    I could write the TIP and implement the the changes in the
    serial drivers SerialCloseProc() for Windows & Posix. But I do
    not feel skilled for the changes in the general channel system.

     
  • Donal K. Fellows

    • status: open --> open-remind