4

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.

JoaoSantos
  • 103
  • 1
  • 6
  • cannot reproduce it - the number of handles stays around 160-200 and does not grow. – alexm Oct 09 '15 at 00:12
  • Neither can I. The number of handles stays at ~260 with 20 threads. Memory rises steadily till 8 MB – Jakub Lortz Oct 09 '15 at 00:20
  • Sharing my project here: https://www.dropbox.com/s/8hk41n7jhex8woi/ConsoleApplication2.zip?dl=0 – JoaoSantos Oct 09 '15 at 00:27
  • I've also noticed this behavior is happening with Visual Studio while in debug mode. Running the console application from the command line, I'm also not being able to reproduce it. This is really strange! – JoaoSantos Oct 09 '15 at 00:29
  • It is the debugger, to be able to use the watch window VS has to extend the lifetime of variables. – Scott Chamberlain Oct 09 '15 at 00:52
  • Although this seems to be happening only while debugging, it doesn't explain why the exponential increase of handles when an exception is thrown (and handled), or am I missing something? – JoaoSantos Oct 09 '15 at 00:55

1 Answers1

0

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.

VMAtm
  • 27,943
  • 17
  • 79
  • 125
  • This happens in both debug and release when running inside VS. If I run from a command line window, it seems stable, so I don't think it has to do with any optimizations. – JoaoSantos Oct 09 '15 at 10:35
  • Ok, then it is because of VS creates this handles for debug purposes. Updated the answer. – VMAtm Oct 09 '15 at 10:48
  • I have also considered that scenario (although it is very very strange to act like that), but today I've tested in another computer and the problem didn't occur (I've updated the original post) – JoaoSantos Oct 09 '15 at 12:59