autofac / Autofac

An addictive .NET IoC container
https://autofac.org
MIT License
4.44k stars 836 forks source link

Can Autofac Dispose queue cause buffer overflow or heap corruption? #1413

Closed WindingWinter closed 4 months ago

WindingWinter commented 4 months ago

This is going to be very vague, so I would appreciate if you can bear with me and give me some pointers or understanding, however vague they could be.

Here's the situation, my nunit console agent crashed with either STATUS_STACK_BUFFER_OVERRUN or heap corruption error, and given that the test list takes a long time to run, I can't easily reproduce the problem in a small sample.

But one thing I do notice is that, if I disable the Autofac container.dispose in just one of the test ( the one that immediately precedes the point where the Nunit console agent crashes), then the nunit console agent will not crash, and can finish running.

If I just run the offending test on its own, then there is no crash at all.

This is the typical structure of my test:

     [Test]
      public void TestStructure()
      {
        var container = GetAutofacContainer();
       // do all the resolve and the AAA thing for unit test

        //finally I dispose the container
          container.Dispose();  //disabling this on the test case immediately preceding to the crash point will stop the nunit agent from crashing
      }

Alternatively, I can also stop the crash by only commenting out the content of a Dispose method of a class ( eg: Undo) that is resolved from Autofac.

In the Undo.Dispose, that's all that I have got, no idea why commenting them will stop the crash:

        private bool _isDisposed;
        public void Dispose()
        {  
         //commenting all the content inside this Dispose method will stop the nunit agent from crashing
            if (_isDisposed) 
                return;
            WeakEventManager<IActionManager, ActionEventArgs>.RemoveHandler(_manager, nameof(IActionManager.ActionOccurred), OnActionOccurred);
            WeakEventManager<IActionManager, EventArgs>.RemoveHandler(_manager, nameof(IActionManager.OnReset), OnReset);
            _isDisposed = true;
        }

And here's another interesting finding:

     [Test]
      public void TestStructure()
      {
        var container = GetAutofacContainer();
       // do all the resolve and the AAA thing for unit test
      var undo = container.Resolve<Undo>();

        //finally I dispose the container
         undo.Dispose();  //dispose undo first, then it wouldn't crash the nunit agent also
          container.Dispose();  
      }

I don't know why if undo.Dispose is called by container.Dispose, then it will crash the nunit agent ( that's my assumption, could be invalid). Is there anything that Autofac dispose handles the dispose differently than how we normally handle it?

tillig commented 4 months ago

When you dispose the container, it calls dispose on any disposable objects you've resolved.

If you can comment out your code's Dispose method and the issue stops, that's a pretty clear indication that the problem is in your code's method. You'll need to debug that yourself; debugging your code for you isn't a service we can offer.