Handle leak when exception is thrown inside task

397 Views Asked by At

I'm trying to understand a very strange handle leak that is occurring in an application. I've managed to isolate the problem in the following code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApplication2
{

    public class EventRaiser
    {
        public event EventHandler OnEvent;

        public void DoSomething()
        {
            Console.Write(".");

            try
            {
                throw new Exception("?");
            }
            catch (Exception e)
            {

            }

            if (OnEvent != null)
                OnEvent(this, null);
        }
    }

    public class EventConsumer
    {
        private EventRaiser m_Event;

        public EventConsumer()
        {
            m_Event = new EventRaiser();
            m_Event.OnEvent += m_Event_OnEvent;

        }

        public void Start()
        {
            m_Event.DoSomething();
        }

        private void m_Event_OnEvent(object sender, EventArgs e)
        {
            Task.Run(() => m_Event.DoSomething() ); // 4.5
            //Task.Factory.StartNew(() => m_Event.DoSomething()); // 4.0
        }
    }

    class Program
    {
        private static EventConsumer x;
        static void Main(string[] args)
        {
            x = new EventConsumer();
            x.Start();

            Console.ReadLine();
        }
    }
}

As is, this test application raises to 23721 handles very very quickly (5 seconds were enough to reach this value)

Task Manager screen shot

However, removing the "throw new Exception" line, the application stays stable with about 450 handles while running for several minutes.

Any idea what is wrong here?

Thanks!

Edit #1

With the warnings of the problem not being reproducible, I've noticed it is happening only when running in debug mode inside Visual Studio (same result in 2013 and 2015 Professional).

Edit #2

Today, I've tested the exact same project on another computer using the exact same version of Visual Studio (2013 Pro 12.0.40629.00 Update5), but this one is running in Windows 8.1 (my computer is running Windows 10), and I was unable to reproduce the problem here.

Edit #3

I've just tested in another computer running Windows 10 and Visual Studio 2015 Pro and again, the problem did not occur! Now I'm very very confused, because I'm having the same problem in my computer while running in Visual Studio 2015 Pro and I have no special extensions installed. I think I'll use the weekend to completely reinstall the system.

1

There are 1 best solutions below

3
On

That can happen because of critical section creation behaviour in .NET. As you know, the catch block are nearly guaranteed to run, and the CLR create some inner constructions to get this done. So I think that the numerous handles are craeted is because of this - you run your code in Task in background, and the are definitely some inner constructions with synchronization.

From other side, why doesn't this be a problem when you are in release mode? Debug mode is being compiled without compiler optimization, for the debug purposes. The Release code is being optimized, and your catch block is empty so I think it's never runs in Release mode - your code simply doesn't throw at all, and that's it.

I can't check right now, but I think that the way to reproduce the problem in Release is to add some code in catch block:

        try
        {
            throw new Exception("?");
        }
        catch (Exception e)
        {
            // log exception here
        }

Update: I think that you are measuring number of handles not for your application (ConsoleApplication2.exe), but for VS created for you for run from itself (ConsoleApplication2.vshost.exe). So this is only about the Visual Studio.