Bug 381 - Memory leak in asp.net with sessions enabled
Summary: Memory leak in asp.net with sessions enabled
Status: NEW
Alias: None
Product: Class Libraries
Classification: Mono
Component: System.Web (show other bugs)
Version: 2.10.x
Hardware: PC Linux
: --- normal
Target Milestone: Untriaged
Assignee: Marek Habersack
Depends on:
Reported: 2011-08-24 11:52 UTC by Justen Hyde
Modified: 2014-09-11 06:46 UTC (History)
6 users (show)

Is this bug a regression?: ---
Last known good build:

test case (72.29 KB, application/x-gzip)
2011-08-24 11:52 UTC, Justen Hyde

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.

Please create a new report for Bug 381 on GitHub or Developer Community if you have new information to add and do not yet see a matching new report.

If the latest results still closely match this report, you can use the original description:

  • Export the original title and description: GitHub Markdown or Developer Community HTML
  • Copy the title and description into the new report. Adjust them to be up-to-date if needed.
  • Add your new information.

In special cases on GitHub you might also want the comments: GitHub Markdown with public comments

Related Links:

Description Justen Hyde 2011-08-24 11:52:16 UTC
Created attachment 179 [details]
test case

A simple web application will consume ever increasing amounts of memory when run with sessions enabled. This appears to be related to CacheItems being created rapidly without being garbage collected. Behaviour seen with both boehm and sgen collection.
See also http://go-mono.com/forums/#nabble-td3264509

Running on mono 2.10.2, observed with both mvc2 (test case attached) and mvc3.

To reproduce: Run the test case, point a couple of browser tabs at it and monitor memory usage over time. This will take a while to become evident (since CacheItems are small).

I suspect this is a cause of the mysterious problems that mono sites under high load experience, referred to here http://www.mono-project.com/Mod_mono#Under_high_load.2C_mono_process_consumes_a_lot_of_memory.2C_website_stops_responding
Comment 1 Jeffrey Stedfast 2011-08-24 12:30:29 UTC
Any chance you could test this on 2.10.4?
Comment 2 Justen Hyde 2011-08-25 16:37:42 UTC
I see exactly the same behaviour on 2.10.4
Comment 4 Jeffrey Stedfast 2011-09-29 12:24:44 UTC
Thanks Justin, looks like some of our devs are now able to reproduce. Hopefully they can find & fix the issue :-)
Comment 6 Miguel de Icaza [MSFT] 2011-12-08 09:43:11 UTC
Gonzalo, was this patch backported to 2-10?

This was on 2011-09-29/2011-09-30
Comment 7 Gonzalo Paniagua Javier 2011-12-08 16:27:31 UTC
commit fc7ffed3acfa9f81943350c846cd393b472cfda0
Author: Gonzalo Paniagua Javier <gonzalo.mono@gmail.com>
Date:   Fri Sep 30 01:20:29 2011 -0400

    Plug an unmanaged memory leak
        If Flush() was called with final_flush set to true, we were leaking the
        unmanaged memory in the output stream (if allocated).
        It was "only" an AS leak.
        Thanks to Kumpera for the help debugging this.
Comment 8 Gonzalo Paniagua Javier 2011-12-08 16:32:20 UTC
...but that leak has nothing to do with sessions or caching
Comment 9 Dan Parnham 2012-01-20 07:56:41 UTC
We're still seeing this issue with mono 2.10.8 unfortunately.

My test case uses the MVC3 and if I set:
<sessionState mode="Off" />
in the web.config it does not leak at all (running through XSP).

I discovered something new today when playing with the SessionState attribute, since we may want to selectively enable/disable session state in our application.

In my test case I set:
    <sessionState mode="InProc" cookieless="false" timeout="20" />
and then used:
in the controller.

This should have the same result as setting the session state mode to off in the web.config, but only applied to specific controllers. However, I still saw leaking of the same magnitude as before! 

Hopefully this information may be useful.
Comment 10 Dan Parnham 2012-01-20 08:36:31 UTC
Update to my previous comment:

Having checked a few things I found that I could still write values into the session in my controller, whereas it should be throwing an exception. It seems that the controller SessionState is not being applied in mono (is this another bug?).

The leak is still happening though and we have been working on the next version of our application in the hope that this problem will be addressed before we have to ship.
Comment 11 pgentoo 2012-10-02 02:51:26 UTC
Any status on this issue?  I also see significant leaks in my application, requiring several restarts per day to keep things running smoothly.  :(
Comment 12 Dan Parnham 2012-10-02 06:38:34 UTC
We gave up hoping that this would be fixed and instead looked for an alternative way of doing things. Since we had javascript heavy single-page application it made sense to switch to a REST service based system running in a console (mono + ubuntu).

We now use the awesome ServiceStack (http://www.servicestack.net/) running as a daemon (https://github.com/ServiceStack/ServiceStack/wiki/Run-ServiceStack-as-a-daemon-on-Linux).

I wrote a post about our problems and solutions at http://blog.teadriven.me.uk/2012/03/time-for-rest.html
Comment 13 Michael Thwaite 2014-09-11 06:46:37 UTC
After a week of trying different web server configurations, XSP, etc., to deal with sessions not being properly ended and hence over-running available memory, I was able to stem the leak significantly, if not 100% by clearing out session variables each time a new session started with this code at the end of the Session_Start event. It more than easily extends web server life from hours to weeks:

			try {
				if (HttpContext.Current.Cache ["Sessions"] == null)
					HttpContext.Current.Cache ["Sessions"] = new List<HttpSessionState> ();

				List<HttpSessionState> Sessions = (List<HttpSessionState>)HttpContext.Current.Cache ["Sessions"];

				List<HttpSessionState> SessionsToGo = new List<HttpSessionState> ();

				DateTime oldSession = DateTime.Now.AddMinutes (c.SessionTimeoutMins); // = -30

				#if (DEBUG)
				oldSession = DateTime.Now.AddMinutes (-1); //for testing

				//Kill old sessions
				Sessions.ForEach (session => {

					if (session != null) {

						if (session ["LastAccess"] != null) {
							DateTime LastAccess = (DateTime)session ["LastAccess"];

							if (LastAccess > DateTime.MinValue && LastAccess < oldSession) {

								//Add reference to SessionsToGo
								SessionsToGo.Add (session);

								session.Clear (); //die

								session.Abandon (); //die - this doesn't seem to work though

				//Remove from collection
				SessionsToGo.ForEach (session => Sessions.Remove (session));

				SessionsToGo = null; //hint to the GC!

				//add this session
				Sessions.Add (HttpContext.Current.Session);

				LogEntry.Write ("Session count:" + Sessions.Count.ToString (), 1019);
			} catch (Exception ex) {
				LogEntry.Write ("Session count/manager suffered an error: " + ex.InnerException.Message, 1019, System.Diagnostics.EventLogEntryType.Warning);