In SocketRead() in Session.NET.cs there's a dubious handling of SocketExceptions. This is what the original code looked like:
```
catch (SocketException exp)
{
if (exp.SocketErrorCode == SocketError.ConnectionAborted)
{
buffer = new byte[length];
this.Disconnect();
return;
}
... // Code removed for brevity
else
throw; // any serious error occurred
}
```
It would seem that the code tries to figure out if "our side" did the disconnect, and then it would send a disconnect message to server, and be done. The problem is that this exception also signals if all sides of the socket is closed. If you use TcpView (sys internals tool) to forcibly close the connection, Disconnect() will be called, and the thread terminates, leaving pending operations such as RunCommand() hanging.
My fix solves *my* particular problem, but I am not sure what impact it has on the rest of the software. This is what I added:
```
catch (SocketException exp)
{
if (this._socket.Connected && // Check if we're still connected
exp.SocketErrorCode == SocketError.ConnectionAborted)
{
buffer = new byte[length];
this.Disconnect();
return;
}
else if (exp.SocketErrorCode == SocketError.WouldBlock ||
exp.SocketErrorCode == SocketError.IOPending ||
exp.SocketErrorCode == SocketError.NoBufferSpaceAvailable)
{
// socket buffer is probably empty, wait and try again
Thread.Sleep(30);
}
else
throw; // any serious error occurred
}
```
The logic is that "If we're not connected anymore via the socket, then something bad happened, and we want outstanding requests to know". The thread of execution will reach the rethrow, which in turn will activate the RaiseError() method further up the stack.
Comments: ** Comment from web user: Euan **
```
catch (SocketException exp)
{
if (exp.SocketErrorCode == SocketError.ConnectionAborted)
{
buffer = new byte[length];
this.Disconnect();
return;
}
... // Code removed for brevity
else
throw; // any serious error occurred
}
```
It would seem that the code tries to figure out if "our side" did the disconnect, and then it would send a disconnect message to server, and be done. The problem is that this exception also signals if all sides of the socket is closed. If you use TcpView (sys internals tool) to forcibly close the connection, Disconnect() will be called, and the thread terminates, leaving pending operations such as RunCommand() hanging.
My fix solves *my* particular problem, but I am not sure what impact it has on the rest of the software. This is what I added:
```
catch (SocketException exp)
{
if (this._socket.Connected && // Check if we're still connected
exp.SocketErrorCode == SocketError.ConnectionAborted)
{
buffer = new byte[length];
this.Disconnect();
return;
}
else if (exp.SocketErrorCode == SocketError.WouldBlock ||
exp.SocketErrorCode == SocketError.IOPending ||
exp.SocketErrorCode == SocketError.NoBufferSpaceAvailable)
{
// socket buffer is probably empty, wait and try again
Thread.Sleep(30);
}
else
throw; // any serious error occurred
}
```
The logic is that "If we're not connected anymore via the socket, then something bad happened, and we want outstanding requests to know". The thread of execution will reach the rethrow, which in turn will activate the RaiseError() method further up the stack.
Comments: ** Comment from web user: Euan **
In all the exceptions I have seen here _socket is null, so it does not fix anything.