[mono/mono] [2 commits] 0b26afc1: Fix memory leaks in Oracle Client. The largest leaks come from the cursors being created but never freed in OracleParameter.cs. The size of the memory used by these cursors varies from tens to thousands of bytes depending on the statement being executed. Several hours of transactions can lead to OOM errors. The other fixes are relatively minor but they do clean up other unmanaged memory not being returned.
Branch: refs/heads/master
Home: https://github.com/mono/mono
Compare: https://github.com/mono/mono/compare/d07562327520...796c64439bed
Commit: 0b26afc1821c941749ff2d21de86a792b8d889f5
Author: Neale Ferguson <[email protected]> (nealef)
Date: 2013-10-10 17:17:17 GMT
URL: https://github.com/mono/mono/commit/0b26afc1821c941749ff2d21de86a792b8d889f5
Fix memory leaks in Oracle Client. The largest leaks come from the cursors being created but never freed in OracleParameter.cs. The size of the memory used by these cursors varies from tens to thousands of bytes depending on the statement being executed. Several hours of transactions can lead to OOM errors. The other fixes are relatively minor but they do clean up other unmanaged memory not being returned.
Changed paths:
M mcs/class/System.Data.OracleClient/System.Data.OracleClient.Oci/OciCalls.cs
M mcs/class/System.Data.OracleClient/System.Data.OracleClient.Oci/OciStatementHandle.cs
M mcs/class/System.Data.OracleClient/System.Data.OracleClient/OracleCommand.cs
M mcs/class/System.Data.OracleClient/System.Data.OracleClient/OracleParameter.cs
Modified: mcs/class/System.Data.OracleClient/System.Data.OracleClient.Oci/OciCalls.cs
===================================================================
@@ -226,6 +226,11 @@ private OciNativeCalls ()
IntPtr usrmempp);
[DllImport ("oci")]
+ internal static extern int OCICacheFree (IntPtr envhp,
+ IntPtr errhp,
+ IntPtr stmthp);
+
+ [DllImport ("oci")]
internal static extern int OCIAttrGet (IntPtr trgthndlp,
[MarshalAs (UnmanagedType.U4)] OciHandleType trghndltyp,
out IntPtr attributep,
@@ -464,7 +469,7 @@ private OciNativeCalls ()
[MarshalAs (UnmanagedType.SysUInt)] int dstlen,
byte [] src,
[MarshalAs (UnmanagedType.SysUInt)] int srclen,
- [MarshalAs (UnmanagedType.SysUInt)] out int rsize);
+ out long rsize);
[DllImport ("oci")]
internal static extern int OCIUnicodeToCharSet (
@@ -473,7 +478,7 @@ private OciNativeCalls ()
[MarshalAs (UnmanagedType.SysUInt)] int dstlen,
[MarshalAs (UnmanagedType.LPWStr)] string src,
[MarshalAs (UnmanagedType.SysUInt)] int srclen,
- [MarshalAs (UnmanagedType.SysUInt)] out int rsize);
+ out long rsize);
}
#endregion
@@ -774,6 +779,16 @@ private OciNativeCalls ()
xtramem_sz, usrmempp);
}
+ internal static int OCICacheFree (IntPtr envhp,
+ IntPtr svchp,
+ IntPtr stmthp)
+ {
+ #if TRACE
+ Trace.WriteLineIf(traceOci, "OCICacheFree", "OCI");
+ #endif
+ return OciNativeCalls.OCICacheFree (envhp, svchp, stmthp);
+ }
+
internal static int OCIAttrGet (IntPtr trgthndlp,
OciHandleType trghndltyp,
out IntPtr attributep,
@@ -1185,24 +1200,37 @@ private OciNativeCalls ()
byte [] src,
out int rsize)
{
+ int rc;
+ long retSize;
+
#if TRACE
Trace.WriteLineIf(traceOci, "OCICharSetToUnicode", "OCI");
#endif
-
- return OciNativeCalls.OCICharSetToUnicode (svchp, dst, dst!=null ? dst.Capacity : 0, src, src.Length, out rsize);
+ rc = OciNativeCalls.OCICharSetToUnicode (svchp, dst,
+ (dst != null ? dst.Capacity : 0),
+ src, src.Length, out retSize);
+ rsize = (int) retSize;
+ return(rc);
}
internal static int OCIUnicodeToCharSet (
IntPtr svchp,
byte [] dst,
- [MarshalAs (UnmanagedType.LPWStr)] string src,
- [MarshalAs (UnmanagedType.SysUInt)] out int rsize)
+ string src,
+ out int rsize)
{
+ int rc;
+ long retSize;
+
#if TRACE
Trace.WriteLineIf(traceOci, "OCIUnicodeToCharSet", "OCI");
#endif
- return OciNativeCalls.OCIUnicodeToCharSet (svchp, dst, dst!=null ? dst.Length : 0, src, src.Length, out rsize);
+ rc = OciNativeCalls.OCIUnicodeToCharSet (svchp, dst,
+ (dst != null ? dst.Length : 0),
+ src, src.Length, out retSize);
+ rsize = (int) retSize;
+ return(rc);
}
[DllImport ("oci")]
Modified: mcs/class/System.Data.OracleClient/System.Data.OracleClient.Oci/OciStatementHandle.cs
===================================================================
@@ -32,6 +32,7 @@ internal sealed class OciStatementHandle : OciHandle, IDisposable
bool moreResults;
OciServiceHandle serviceHandle;
ArrayList values;
+ ArrayList parm;
OracleCommand command;
#endregion // Fields
@@ -82,12 +83,11 @@ protected override void Dispose (bool disposing)
if (disposing) {
if (values != null) {
- foreach (OciDefineHandle h in values)
+ foreach (OciDefineHandle h in values)
h.Dispose ();
values = null;
}
}
-
base.Dispose (disposing);
}
}
@@ -110,6 +110,9 @@ public OciParameterDescriptor GetParameter (int position)
OciParameterDescriptor output = new OciParameterDescriptor (this, handle);
output.ErrorHandle = ErrorHandle;
+ if (parm == null)
+ parm = new ArrayList();
+ parm.Add(handle);
return output;
}
@@ -228,6 +231,8 @@ public bool Fetch ()
switch (status) {
case OciGlue.OCI_NO_DATA:
moreResults = false;
+ foreach (IntPtr h in parm)
+ OciCalls.OCIDescriptorFree(h, OciHandleType.Parameter);
break;
case OciGlue.OCI_DEFAULT:
moreResults = true;
Modified: mcs/class/System.Data.OracleClient/System.Data.OracleClient/OracleCommand.cs
===================================================================
@@ -27,6 +27,7 @@
using System.Data.OracleClient.Oci;
using System.Drawing.Design;
using System.Text;
+using System.Threading;
namespace System.Data.OracleClient
{
@@ -268,6 +269,7 @@ private void AssertTransactionMatch ()
private void BindParameters (OciStatementHandle statement)
{
+Console.Error.WriteLine("{0} - BindParameter",Thread.CurrentThread.ManagedThreadId);
for (int p = 0; p < Parameters.Count; p++)
Parameters[p].Bind (statement, Connection, (uint) p);
}
@@ -705,7 +707,7 @@ private OciStatementHandle GetStatementHandle ()
private void SafeDisposeHandle (OciStatementHandle h)
{
- if (h != null && h != preparedStatement)
+ if (h != null && h != preparedStatement)
h.Dispose();
}
@@ -757,6 +759,9 @@ void Prepare ()
protected override void Dispose (bool disposing)
{
+ if (preparedStatement != null)
+ OciCalls.OCIHandleFree(preparedStatement,
+ OciHandleType.Statement);
if (disposing)
if (Parameters.Count > 0)
foreach (OracleParameter parm in Parameters)
Modified: mcs/class/System.Data.OracleClient/System.Data.OracleClient/OracleParameter.cs
===================================================================
@@ -821,8 +821,11 @@ internal void Bind (OciStatementHandle statement, OracleConnection con, uint pos
if (direction == ParameterDirection.Output ||
direction == ParameterDirection.InputOutput ||
direction == ParameterDirection.ReturnValue) {
-
- cursor = IntPtr.Zero;
+ if (cursor != IntPtr.Zero) {
+ OciCalls.OCIHandleFree (cursor,
+ OciHandleType.Statement);
+ cursor = IntPtr.Zero;
+ }
OciCalls.OCIHandleAlloc (connection.Environment,
out cursor,
OciHandleType.Statement,
Commit: 796c64439bedc67608d9ac9ec7f74fde595dc1bb
Author: Rodrigo Kumpera <[email protected]> (kumpera)
Date: 2013-10-10 18:26:54 GMT
URL: https://github.com/mono/mono/commit/796c64439bedc67608d9ac9ec7f74fde595dc1bb
Merge pull request #776 from nealef/master
Fix memory leaks in Oracle Client. The largest leaks come from the curso...
Changed paths:
M mcs/class/System.Data.OracleClient/System.Data.OracleClient.Oci/OciCalls.cs
M mcs/class/System.Data.OracleClient/System.Data.OracleClient.Oci/OciStatementHandle.cs
M mcs/class/System.Data.OracleClient/System.Data.OracleClient/OracleCommand.cs
M mcs/class/System.Data.OracleClient/System.Data.OracleClient/OracleParameter.cs
Modified: mcs/class/System.Data.OracleClient/System.Data.OracleClient.Oci/OciCalls.cs
===================================================================
@@ -226,6 +226,11 @@ private OciNativeCalls ()
IntPtr usrmempp);
[DllImport ("oci")]
+ internal static extern int OCICacheFree (IntPtr envhp,
+ IntPtr errhp,
+ IntPtr stmthp);
+
+ [DllImport ("oci")]
internal static extern int OCIAttrGet (IntPtr trgthndlp,
[MarshalAs (UnmanagedType.U4)] OciHandleType trghndltyp,
out IntPtr attributep,
@@ -464,7 +469,7 @@ private OciNativeCalls ()
[MarshalAs (UnmanagedType.SysUInt)] int dstlen,
byte [] src,
[MarshalAs (UnmanagedType.SysUInt)] int srclen,
- [MarshalAs (UnmanagedType.SysUInt)] out int rsize);
+ out long rsize);
[DllImport ("oci")]
internal static extern int OCIUnicodeToCharSet (
@@ -473,7 +478,7 @@ private OciNativeCalls ()
[MarshalAs (UnmanagedType.SysUInt)] int dstlen,
[MarshalAs (UnmanagedType.LPWStr)] string src,
[MarshalAs (UnmanagedType.SysUInt)] int srclen,
- [MarshalAs (UnmanagedType.SysUInt)] out int rsize);
+ out long rsize);
}
#endregion
@@ -774,6 +779,16 @@ private OciNativeCalls ()
xtramem_sz, usrmempp);
}
+ internal static int OCICacheFree (IntPtr envhp,
+ IntPtr svchp,
+ IntPtr stmthp)
+ {
+ #if TRACE
+ Trace.WriteLineIf(traceOci, "OCICacheFree", "OCI");
+ #endif
+ return OciNativeCalls.OCICacheFree (envhp, svchp, stmthp);
+ }
+
internal static int OCIAttrGet (IntPtr trgthndlp,
OciHandleType trghndltyp,
out IntPtr attributep,
@@ -1185,24 +1200,37 @@ private OciNativeCalls ()
byte [] src,
out int rsize)
{
+ int rc;
+ long retSize;
+
#if TRACE
Trace.WriteLineIf(traceOci, "OCICharSetToUnicode", "OCI");
#endif
-
- return OciNativeCalls.OCICharSetToUnicode (svchp, dst, dst!=null ? dst.Capacity : 0, src, src.Length, out rsize);
+ rc = OciNativeCalls.OCICharSetToUnicode (svchp, dst,
+ (dst != null ? dst.Capacity : 0),
+ src, src.Length, out retSize);
+ rsize = (int) retSize;
+ return(rc);
}
internal static int OCIUnicodeToCharSet (
IntPtr svchp,
byte [] dst,
- [MarshalAs (UnmanagedType.LPWStr)] string src,
- [MarshalAs (UnmanagedType.SysUInt)] out int rsize)
+ string src,
+ out int rsize)
{
+ int rc;
+ long retSize;
+
#if TRACE
Trace.WriteLineIf(traceOci, "OCIUnicodeToCharSet", "OCI");
#endif
- return OciNativeCalls.OCIUnicodeToCharSet (svchp, dst, dst!=null ? dst.Length : 0, src, src.Length, out rsize);
+ rc = OciNativeCalls.OCIUnicodeToCharSet (svchp, dst,
+ (dst != null ? dst.Length : 0),
+ src, src.Length, out retSize);
+ rsize = (int) retSize;
+ return(rc);
}
[DllImport ("oci")]
Modified: mcs/class/System.Data.OracleClient/System.Data.OracleClient.Oci/OciStatementHandle.cs
===================================================================
@@ -32,6 +32,7 @@ internal sealed class OciStatementHandle : OciHandle, IDisposable
bool moreResults;
OciServiceHandle serviceHandle;
ArrayList values;
+ ArrayList parm;
OracleCommand command;
#endregion // Fields
@@ -82,12 +83,11 @@ protected override void Dispose (bool disposing)
if (disposing) {
if (values != null) {
- foreach (OciDefineHandle h in values)
+ foreach (OciDefineHandle h in values)
h.Dispose ();
values = null;
}
}
-
base.Dispose (disposing);
}
}
@@ -110,6 +110,9 @@ public OciParameterDescriptor GetParameter (int position)
OciParameterDescriptor output = new OciParameterDescriptor (this, handle);
output.ErrorHandle = ErrorHandle;
+ if (parm == null)
+ parm = new ArrayList();
+ parm.Add(handle);
return output;
}
@@ -228,6 +231,8 @@ public bool Fetch ()
switch (status) {
case OciGlue.OCI_NO_DATA:
moreResults = false;
+ foreach (IntPtr h in parm)
+ OciCalls.OCIDescriptorFree(h, OciHandleType.Parameter);
break;
case OciGlue.OCI_DEFAULT:
moreResults = true;
Modified: mcs/class/System.Data.OracleClient/System.Data.OracleClient/OracleCommand.cs
===================================================================
@@ -27,6 +27,7 @@
using System.Data.OracleClient.Oci;
using System.Drawing.Design;
using System.Text;
+using System.Threading;
namespace System.Data.OracleClient
{
@@ -268,6 +269,7 @@ private void AssertTransactionMatch ()
private void BindParameters (OciStatementHandle statement)
{
+Console.Error.WriteLine("{0} - BindParameter",Thread.CurrentThread.ManagedThreadId);
for (int p = 0; p < Parameters.Count; p++)
Parameters[p].Bind (statement, Connection, (uint) p);
}
@@ -705,7 +707,7 @@ private OciStatementHandle GetStatementHandle ()
private void SafeDisposeHandle (OciStatementHandle h)
{
- if (h != null && h != preparedStatement)
+ if (h != null && h != preparedStatement)
h.Dispose();
}
@@ -757,6 +759,9 @@ void Prepare ()
protected override void Dispose (bool disposing)
{
+ if (preparedStatement != null)
+ OciCalls.OCIHandleFree(preparedStatement,
+ OciHandleType.Statement);
if (disposing)
if (Parameters.Count > 0)
foreach (OracleParameter parm in Parameters)
Modified: mcs/class/System.Data.OracleClient/System.Data.OracleClient/OracleParameter.cs
===================================================================
@@ -821,8 +821,11 @@ internal void Bind (OciStatementHandle statement, OracleConnection con, uint pos
if (direction == ParameterDirection.Output ||
direction == ParameterDirection.InputOutput ||
direction == ParameterDirection.ReturnValue) {
-
- cursor = IntPtr.Zero;
+ if (cursor != IntPtr.Zero) {
+ OciCalls.OCIHandleFree (cursor,
+ OciHandleType.Statement);
+ cursor = IntPtr.Zero;
+ }
OciCalls.OCIHandleAlloc (connection.Environment,
out cursor,
OciHandleType.Statement,
_______________________________________________
Mono-patches maillist - [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches
lmpx.com only provides a reader for public news (NNTP) servers. It is not
affiliated with the servers or forums shown here and is not responsible for
the content of articles, which is written by their respective authors.