yebetrollin
yebetrollin

Reputation: 101

Application crash without throwing exception if Socket.BeginSend is called after the socket is closed

I'm writing a socket application that asynchronously polls several servers at once and reports any changes in their states to the user. So far everything is working, except for one small bug I can't seem to figure out.

The server creates a bunch of sockets every 10 seconds, then calls an async connect. This is then handled by a ProcessConnectionComplete(IAsyncResult iar) method, which then calls both Socket.BeginReceive and then Socket.Begin send. Any received data is then handled with another method.

Then, at the end of the 10 seconds before the next wave of sockets is created, any sockets that have not already received data and closed are forcefully closed by a loop.

The issue I am having is that if the socket happens to close just before the Socket.BeginSend method is called (ie someone trips over a network cable, or the server on the other end crashes), the program exits without exeption (error code 0), when it should throw an exception. Here's the code:

private static void ProcessConnectionComplete(IAsyncResult iar)
{
    SocketState state = iar.AsyncState as SocketState;
    if (state.Socket.Connected)
    {
        // start waiting for a reply
        state.Socket.BeginReceive(state.Buffer, 0, state.Buffer.Length, SocketFlags.None, new AsyncCallback(frm_Server_Poll.ProcessAsyncReceive), state);

        //state.Socket.Close(); // if socket is closed after .Connected check and before BeginSend, crash occurs
        try
        {
            // send message
            state.Socket.BeginSend(new byte[] { (byte)'\xfe' }, 0, 1, SocketFlags.None, null, state);
        }
        catch (Exception ex) // Never called, EXCEPTION WHERE ARE YOU???
        {
            throw (ex);
        }
    }
    else
    {
        state.ServerInfo.connected = false;
    }
}

Why is this happening? I have some idea that it is to do with the way threading is handled with Async calls, but have no idea how to catch the exception. Any help would be greatly appreciated.

Upvotes: 2

Views: 3230

Answers (2)

user207421
user207421

Reputation: 310840

if the socket happens to close just before the Socket.BeginSend method is called (ie someone trips over a network cable, or the server on the other end crashes)

I do not understand. Neither of those events will close your socket. Only you can close your socket. Those events can abort the connection, in which case your send will get whatever exception an ECONNRESET maps to in C#. If you close the socket yourself and then send, you will get whatever EBADF maps to if nothing else in C# traps it first.

Upvotes: 0

Chris Chilvers
Chris Chilvers

Reputation: 6479

The exception should occur in the callback (frm_Server_Poll.ProcessAsyncReceive) when calling Socket.EndReceive.

Likewise, for the send, the exception should occur in its callback when calling Socket.EndSend. However, your BeginSend does not have a callback with which to handle errors.

I cannot be certain, but I suspect that this is why the exception is getting mysteriously lost.

It's worth noting that both BeginReceive and BeginSend can throw directly if the socket is disposed at the time they are called.

Upvotes: 1

Related Questions