Huge memory leak when using ODP.NET from http handler under IIS
530856Aug 30 2006 — edited Feb 28 2008I am developing a .NET Remoting application which uses an http handler running under IIS for streaming data from a server down to its clients. This works just fine. Until I open an oracle database connection before I stream the data. After I have opened the connection (and closed it again properly) all the data I am streaming will leak on the server, causing it to consume huge amounts of memory. Note that the leaking data is not connected to the database at all.
Can anyone figure out how opening an oracle connection affects streaming using System.Web? It works fine if I open a connection to a MSSQL database, or to oracle using the Microsoft provider in System.Data.OracleClient instead of ODP.NET.
I am running Windows Server 2003, IIS 6, .NET 2.0 and have tried both ODP.NET 10.2.0.1.0 and 10.2.0.2.20.
This is an example of a leaking http handler:
---
using System;
using System.Web;
using Oracle.DataAccess.Client;
namespace MemoryLeak {
class LeakingHttpHandler : IHttpHandler {
public bool IsReusable { get { return true; } }
public void ProcessRequest(HttpContext context) {
using (OracleConnection conn = new OracleConnection("...")) {
conn.Open();
}
context.Response.Buffer = false;
for (int i = 0; i < 100; i++) {
byte[] buffer = new byte[65536];
context.Response.OutputStream.Write(buffer, 0, buffer.Length);
}
context.Response.End();
}
}
}
---
The http handler is set up with the following Web.config file:
---
<configuration>
<system.web>
<httpRuntime executionTimeout="1800" />
<httpHandlers>
<add verb="*" path="*.rem" type="MemoryLeak.LeakingHttpHandler, MemoryLeak" />
</httpHandlers>
</system.web>
</configuration>
---
After creating a virtual directory in IIS (called MemoryLeak) I just have to enter the correct url in Internet Explorer (http://localhost/memoryleak/foo.rem) a few times to make the memory consumption of w3wp.exe go sky high.
If I remove conn.Open() from the code, the memory leak disappears.
If I set context.Response.Buffer = true (which I do not want to do), the memory leak disappears.
If I start a new thread, open the oracle connection in that new thread, and join with the thread, the memory leak disappears.
And note again that the leaking data is the data I send into the call to context.Response.OutputStream.Write, i.e. many megabytes, not the database connection itself.