Tcl Source Code

Ticket Change Details
Login
Overview

Artifact ID: 0c6a16db60e52858792ed35de9315af59c1e24a3
Ticket: 97069ea11aca3783949c0379725eed90f5573c23
close returns empty error message if failed non-blocking write flush pending
User & Date: oehhar 2014-03-25 09:55:25
Changes

  1. comment changed to:
    <h1>Issue</h1>
    The trailing close in the following sequence throws an error but no error message:
    <verbatim>
    % set sock [socket -async localhost 30001]
    sock420
    % fconfigure $sock -blocking 0
    % puts $sock ok
    % flush $sock
    % fileevent $sock writable {set x 1}
    % vwait x
    % catch {close $sock} e d
    1
    % set e
    % set d
    -code 1 -level 0 -errorstack {INNER {invokeStk1 close sock420}} -errorcode NONE
    -errorinfo {
        while executing
    "close $sock"} -errorline 1
    </verbatim>
    
    There are two conditions:
       *   The socket connect must fail
       *   flush $sock is executed before the socket connect internally failed. For machines where this is to quick, one must use another host instead localhost which requires a long DNS query.
       *   There are also relations with multiple connect rounds within an IPV6 enabled system (TCL8.6.1 Linux).
    
    This arises on the following platforms:
       *   TCL 8.5.15 on Windows Vista 32 bit 
       *   TCL 8.6.1 on Windows Vista 32 bit
       *   TCL 8.6.1 on Linux too (Reported bei Reinhard Max)
    
    <h1>Possible reasons</h1>
    
    The error is generated by a backround flush sheduled by the writable event.
    The error code is stored in unreportedError.
    Eventually, the error message is missing in unreportedMsg.
    
    A debug trace on tclIO.c:
    
    <h2>flush $sock</h2>
       *   tclIO.c:FlushChannel()
       *   calls tclWinSock.c:TclOutputProc("ok"), which returns error EWOULDBLOCK
       *   Sets flag BG_FLUSH_SCHEDULED
       *   Clears error
    
    <h2>vwait x</h2>
       *   tclIO.c:FlushChannel(calledFromAsyncFlush=1)
       *   calls tclWinSock.c:TclOutputProc("ok"), which tries to write and returns error 126
       *   Sets statePtr->unreportedError = errorCode (126)
       *   statePtr->unreportedMsg = msg (NULL)
       *   Calls DiscardOutputQueued(statePtr)
       *   Flag BG_FLUSH_SCHEDULED is cleared (no data)
    
    <h2>close $sock</h2>
       *   tclIO.c:Tcl_Close()
       *   > Tcl_Close calls FlushChannel(interp, chanPtr, 0)
       *   >> FlushChannel calls CloseChannel(interp, chanPtr, errorCode)
       *   >>> CloseChannel calls ChanClose(chanPtr, interp)
       *   >>>> ChanClose calls tclWinSock.c:TclCloseProc(), which succeeds
       *   >>> CloseChannel sets errorCode = statePtr->unreportedError; (126)
       *   >>> CloseChannel calls Tcl_SetChannelErrorInterp() with NULL statePtr->unreportedMsg
       *   >>> CloseChannel returns errorCode (126)
       *   >> FLushChannel returns errorCode (126)
       *   > Tcl_Close returns error: if ((flushcode != 0) || (result != 0)) { return TCL_ERROR; }
    
  2. login: "oehhar"
  3. mimetype: "text/plain"