2

Closed

Exception called in ReusableSocketNetworkStream Finalizer

description

Using 1.1 Build 54198 I have got the following error reported from a customer:
 
System.Net.Sockets.SocketException: A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied
at System.Net.Sockets.Socket.Disconnect(Boolean reuseSocket)
at HttpServer.ReusableSocketNetworkStream.Dispose(Boolean disposing)
at System.Net.Sockets.NetworkStream.Finalize()
 
 
Looking at ReusableSocketNetworkStream.Dispose(bool) I see that contrary to .Net dispose pattern the socket is disposed regardless of disposing value. Could this be the problem?
 
If so the suggested new code would be:
 
    protected override void Dispose(bool disposing)
    {
        if (disposed) return;
 
        try
        {
            if (disposing)
            {
                if (Socket != null && Socket.Connected)
                {
                    try
                    {
                        Socket.Disconnect(true);
                    }
                    catch (ObjectDisposedException) { }
                }
            }
        }
        finally
        {
            base.Dispose(disposing);
            disposed = true;
        }
    }
 
 
Alternatively, is there a concurrency problem?
 
Also Close() should check the disposed property. Suggested new implementation:
 
    public override void Close()
    {
        if (disposed) throw new ObjectDisposedException(GetType().FullName);
        if (Socket != null && Socket.Connected)
            Socket.Close(); //TODO: Maybe use Disconnect with reuseSocket=true? I tried but it took forever.
 
        base.Close();
    }
Closed Jan 31, 2012 at 4:54 AM by jgauffin

comments

high wrote Dec 8, 2011 at 4:04 PM

Ya the disposing pattern is not really followed here. Although cleaning up a socket should probably be part of the unmanaged cleanup either way. Anyways this exception is caused when a socket is disconnected causing an exception before its fully accepted. So the garbage collector ends up getting the socket calling the finalizer. And because the socket is not connected the dispose method throws an exception.

A simple fix would be

try
{
if (Socket != null && Socket.Connected)
    Socket.Disconnect(true);
}
catch (SocketException se)
{
_logger.Warning("Exception on disconnecting stream", se);
}

Probably the best solution at this point seeing as I don't think the sockets are properly disposed of in all cases anyways.

wrote Jan 31, 2012 at 4:54 AM

wrote Feb 21, 2013 at 11:29 PM

wrote May 16, 2013 at 11:01 AM