Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Visual Studio 2010 doesn’t stop at an unhandled exception inside a Socket.BeginReceive() callback - why?

Normally, when the debugger is attached, Visual Studio 2010 stops at an unhandled exception even if the Exceptions dialog doesn’t have the tickmark for the exception type in the “Thrown” column. The keyword here is unhandled; said dialog refers only to handled exceptions.

However, in the following minimal example, Visual Studio 2010 does not stop at the exception for me, even though it appears in the Immediate Window as a first-chance exception:

EDIT: The first minimal example I posted was fixed by the first answer I received, but unfortunately the following example still exhibits the problem:

using System;
using System.Net.Sockets;

namespace SocketTest
{
    class Program
    {
        static void Main(string[] args)
        {
            var listener = new TcpListener(8080);
            listener.Start();
            AsyncCallback accepter = null;
            accepter = ar =>
            {
                var socket = listener.EndAcceptSocket(ar);
                var buffer = new byte[65536];
                AsyncCallback receiver = null;
                receiver = ar2 =>
                {
                    var bytesRead = socket.EndReceive(ar2);
                    throw new InvalidOperationException();
                    socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, receiver, null);
                };
                socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, receiver, null);
                listener.BeginAcceptSocket(accepter, null);
            };
            listener.BeginAcceptSocket(accepter, null);

            Console.WriteLine("Feel free to connect to port 8080 now.");
            Console.ReadLine();
        }
    }
}

If you run this, connect to it by running telnet localhost 8080 and then type any character into telnet, hopefully you will see what I see: the program just aborts silently.

Why does Visual Studio apparently swallow this exception? Can I get it to break at the exception as it usually does?

(Interestingly, throwing inside the BeginAcceptSocket callback does get caught, as does an exception in a normal thread started with Thread.Start. I can only reproduce the issue by throwing inside the BeginReceive callback.)

like image 365
Timwi Avatar asked Nov 19 '11 20:11

Timwi


People also ask

How do I break an exception in Visual Studio?

Tell the debugger to break when an exception is thrownIn the Exception Settings window (Debug > Windows > Exception Settings), expand the node for a category of exceptions, such as Common Language Runtime Exceptions. Then select the check box for a specific exception within that category, such as System.

What is user unhandled exception in C#?

An unhandled exception occurs when the application code does not properly handle exceptions. For example, When you try to open a file on disk, it is a common problem for the file to not exist. The . NET Framework will then throw a FileNotFoundException.


3 Answers

This is a known bug in CLR version 4. The feedback article is here. A possible workaround is to change the framework target to version 3.5. I'll just quote the relevant portion of the feedback response:

We have investigated the issue and determined there is a bug in CLR v4.0 which causes this. The process does throw the exception (you can catch it with a catch handler for example) but the debugger was not properly notified of the unhandled exception. This causes the process to appear to exit without any indication from the debugger about what happened. We have investigated potential fixes, however all of the fixes had moderate risk of breaking other functionality. Because it was very late in product cycle we decided it was safer not to fix this issue and risk creating new bugs. We will continue to track this issue as part of our next release cycle.

The issue is restricted to exceptions that escape managed code where the thread was created using a few specific API calls:
new System.Threading.Timer()
ThreadPool.UnsafeQueueNativeOverloapped
ThreadPool.BindHandle
ThreadPool.RegisterWaitForSingleObject.

It is RegisterWaitForSingleObject() in this specific case.

like image 131
Hans Passant Avatar answered Oct 19 '22 11:10

Hans Passant


Since you see only a 'Thrown' checkbox in the exception settings, my suspicion is that you have '.Net Framework Source Stepping' enabled in your debug settings. If you enable 'Just My Code' (which disables '.Net Framework Source Stepping'), you should get 'User-Unhandled' and 'Thrown' checkboxes in your exception settings dialog and you will also catch the exception in the debugger.

Screen Shot O' Victory:

Screenshot showing the debugger halted at the exception as expected

like image 39
Ritch Melton Avatar answered Oct 19 '22 12:10

Ritch Melton


This is what I have discovered so far:

  1. If no exceptions are explicitly checked in the Debug->Exceptions dialog and Options->Debugging->"Enable Just My Code" (EJMC) is not checked, then an exception thrown in any of the callbacks will not break with First Chance Exception (FCE)

  2. If no exceptions are explicitly checked in the Debug->Exceptions dialog and EJMC is checked, then an exception thrown in the TCPListener's callback will break with FCE, but will not break with FCE in the Socket's callback

    a. An exception thrown will not break with FCE in the Socket's callback, even if the TCPListener's blocking AcceptSocket() is called (so no callback for listener).

  3. If System.InvalidOperationException (or System) is checked in Debug->Exceptions, then an appropriate exception thrown in any of the callbacks will break with FCE, regardless of whether EJMC is checked or not.

  4. The above is true whether the callbacks are specified as lambda or in an excplicit user function

I do not know why VS does not break with FCE in the socket callback if the exception is not excplicitly checked in Debug->Exceptions (what makes the socket callback different from the listener callback).

like image 32
Attila Avatar answered Oct 19 '22 12:10

Attila