MediaBrowser / SocketHttpListener

A standalone HttpListener with support for SSL, WebSockets and Mono
MIT License
42 stars 14 forks source link

Memory leak? #21

Open sp00x opened 6 years ago

sp00x commented 6 years ago

I did something as simple as this (see below), and then had a batch file that just does CURL over and over and over against this endpoint.

For each request, there is one instance of HttpListenerRequest, HttpListenerResponse, HttpListenerContext, HttpConnection and several other types being left unreleased, according to general memory usage as report by task manager but also .NET memory profilers such as https://memprofiler.com/ (and the fact that it crashes with EOutOfMemoryException if left alone for a while).

I thought a simple .Response.Close() would be enough, but apparently not..? .Abort() does not help either, nor does setting KeepAlive = false.

MSVS 2012, .NET 4.6.1, installed from NuGET (1.0.50)

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

namespace ConsoleApplication29
{
    class Program
    {
        static void Main(string[] args)
        {
            var listener = new HttpListener();
            listener.Prefixes.Add("http://+:8899/");
            listener.OnContext = (HttpListenerContext context) =>
            {
                Console.WriteLine("request " + DateTime.Now);
                context.Response.KeepAlive = false; // nope
                context.Response.Close(); // nope
                //context.Response.Abort(); // nope
            };
            listener.Start();
            Console.ReadKey();
        }
    }
}
LukePulverenti commented 6 years ago

This may have been a primary reason for our application using this library to often have runaway memory usage under the .net framework. We moved to .net core and it hasn't been a problem since then.

Just FYI, this library is intended to more or less be a clone of the mono HttpListener along with web socket support and a few other bug fixes, so it's unlikely that I'm going to tear it apart to try and get to the bottom of what is happening here.

The .net core HttpListener is a complete rewrite, so perhaps some inspiration could be taken from it: https://github.com/dotnet/corefx/tree/master/src/System.Net.HttpListener/src/System/Net

Additionally on .NET Core, kestrel is also a nice option. You should only be using this library if you need to be able to run under the mono runtime. If you only need .NET framework and/or .NET core support, then i would just use the built-in HttpListener.

sp00x commented 6 years ago

The reason why I switched to this in the first place was the really cumbersome setup of https with the .NET HttpListener classes, where you have to import the certificates and register the cert with a fingerprint and clsid and all those magic dance moves to even get it working.

Anyway, I ported my code back to the .NET framework HttpListener now, and will just have to deal with SSL the clumsy way for now.

But anyway, might be worth leaving this issue as a warning for anyone else tempted to use it :)

euphoricz commented 5 years ago

Looking through the source, disposable objects such as input and output streams associated with the request and response (as well as others) are not being disposed of, this is one of the primary reasons for the leak.

Much of the leak could be fixed by disposing of disposable objects in the close method of HttpConnection since this is the heart of it.