ChallengeFind the resource leak

time to read 3 min | 549 words

I am not sure if I should be embarrassed or furious about this bug, but I spent a lot of time working on issue. Basically, I had a resource leak in my app. I knew that I had it, and even though it took a while to create a reliable reproduction, I managed to narrow it down to a simple reproduction. It was obvious that the issue is leaking resources during the shutdown phase of the application as a result of a race condition.

Now, usually we don’t care about such things because shutting down will, obviously, clear all of those nasty things anyway. Unfortunately, my scenario is to start & shutdown many times in a single process, as part of a unit test. So I had to figure out what was actually going on. The maddening part is that the code should work.

Here is a close approximation of the code in question:

public class QueueActions : IDisposable
{
    UnmanagedDatabaseConnection database;
    public string Name { get; private set; }

    public class QueueActions( UnmanagedDatabaseConnectionFactory factory)
    {
         database = factory.Create();
         database.Open(()=> Name = database.ReadName());
    }

   // assume proper GC finalizer impl

    public void Dispose()
    {
          database.Dispose();
    }
}

And the code using this:

using(var factory = CreateFactory())
{
   ThreadPool.QueueUserWorkItem(()=>
   {
          using(var actions = new QueueActions(factory))
          {
               actions.Send("abc");     
          }
    });
}

Note that this isn’t remotely like the actual code, it is highly simplified

And yes, there is an intentional race condition here.

Here are two pieces of information that are important to remember about this unmanaged library:

  • The factory will not close if there are opened connections (exception)
  • Trying to open a connection after the factory was closed will fail (exception)

How many problems does the code above have?

More posts in "Challenge" series:

  1. (03 Jan 2020) Spot the bug in the stream–answer
  2. (15 Feb 2010) Where is the optimization?