mono/mono — pull request #979 by BrandonLWhite (2014-04-03 01:23:01+00:00)
Title: Fixed memory leak in Tasks when child tasks are continually created from...

... within an ancestor Task. This resolves bug # 18398 (https://bugzilla.xamarin.com/show_bug.cgi?id=18398) and other OOM scenarios in long running applications that make use of FromAsync, ContinueWith, etc. to "rearm" asynchronous operations.

Hi, while investigating an OOM scenario in my server application that uses SignalR and Katana/OWIN I came to discover that Mono was leaking memory with Task constructs such as FromAsync and ContinueWith. Further analysis (you can read to gory details in the bugzilla thread) showed that the leak only happened when a new Task was created from within the thread of execution of another task.

The root cause of the leak stems from the use of the `parent` field in Task. Whenever as part of a Task handler you fire off a new task, the current task becomes the parent of the new task. This `parent` reference in the new task prevents the GC from being able to collect the old finished task. This gets real bad in typical server code, where you asynchronously handle stuff and then FromAsync or whatever to setup subsequent requests. What you end up with is an infinitely descending chain of Task objects, and eventually you run out of memory and crash.

The fix is simple. When the Task is finished (or Dispose'd), set the parent to null to break the reference. The GC can then do it's job. In my test app that was leaking like crazy, memory utilization is now rock solid.

If there is anything else I need to do in order for this PR to be accepted, I'm ready and willing. It would totally make my day to get a commit into Mono!