In tclhttpd3.1 I encountered a problem of "leaking" sockets.

In Httpd_ReturnFile there is a call to Httpd_Suspend:
Httpd_Suspend $sock 0
that removes any fileevent listeners on the socket and any cleanup timer event
handlers.

The Httpd_ReturnFile then does a fcopy:
fcopy $in $sock -command [list HttpdCopyDone $in $sock $close ]

The problem arises if the browser breaks the connection during the fcopy.
(Try many reloads of  a page from a localhost server using IE).
fcopy does not call the callback when this happens and the Http socket data never

gets cleaned up. (I am  not sure if the socket itself gets closed  or not - I
suspect
it doesn't due to some browser errors about tcp memory I am getting).

>From the fcopy docs:
>You are not allowed to do other I/O operations with inchan or outchan during a
background fcopy.
>If either inchan or outchan get closed while the copy is in progress, the
current copy is stopped and
>the command callback is not made. If inchan is closed, then all data already
queued for outchan is
        ^^^^^^^^^^^^^^^^^^^^^^^
>written out.

A fix is to add an event listener on the socket after the suspend :
        Httpd_Suspend $sock 0
        fileevent $sock readable [list Httpd_CopyFailed $sock]
        fcopy $in $sock -command [list HttpdCopyDone $in $sock $close ]

which  closes the socket:
proc Httpd_CopyFailed {sock} {
    fileevent $sock readable {}
    Httpd_SockClose $sock 1  ""
}

Of course from the fcopy docs

>Note that inchan can become readable during a background copy. You should turn
off any fileevent
>handlers during a background copy so those handlers do not interfere with the
copy. Any I/O
>attempted by a fileevent handler will get a "channel busy" error.

Though of course we aren't doing IO - just closing the socket.


Brent - is this a correct fix?

-Jeff McWhirter




Reply via email to