AccessViolationException / SEHException while calling open/close
Posted: Thu 16 May 2013 10:55
Hello,
We have a rather large application that's working with multiple parallel OracleConnections. Every few days we get an unrecoverable AccessViolationException while calling the connections open or close method. Although we're not able to reliably and exactly reproduce the problem in the application we were able to create a small sample application that at least forces the the AccessViolationException (rarely SEHException) while calling Close().
In general we're running several parallel tasks, each of this task loops on connection open, close and dispose.
After about 16300 open/close (should be within less than one minute) things start getting messy:
At first I get exceptions that the Server did not respond within the specified timeout interval, then all hell breaks lose:
ORA 01041 (internal error), 12536 (operation would block), 12560 (TNS protocol adapter), 12650 (encryption and data integrity) are thrown seemingly randomly. It's usually not all of the above mentioned error codes, but most of them;
I don't care that much about those error codes (at least not in this sample context) - the problem is that several seconds after those errors start occuring, I get an unhandled Exception:
With Devart 7.7.226 I get the following:
With Devart 7.2.96 and 7.2.114 I sometimes got this one instead:
I thought that maybe the installed Oracle Drivers could be the issue, but I ran the sample application with Oracle's ODP as well: It throws the ORA errors as well, but as soon as the server is ready again, it's connecting again. As of now I have installed just one ORA Client so the driver itself shouldn't be the issue. (if there's a way to specify a specific ORA_HOME for Devart to use I'll gladly try that too)
Can you please take a look at this issue and provide a bugfix and/or a workaround to resolve this? If you have any problem reproducing the error feel free to use my sample (see below) or ask.
Looking forward to hear from you,
Klaus
Here's the sample I ran in a .NET 4.5 console application (x86 and x64)
We have a rather large application that's working with multiple parallel OracleConnections. Every few days we get an unrecoverable AccessViolationException while calling the connections open or close method. Although we're not able to reliably and exactly reproduce the problem in the application we were able to create a small sample application that at least forces the the AccessViolationException (rarely SEHException) while calling Close().
In general we're running several parallel tasks, each of this task loops on connection open, close and dispose.
After about 16300 open/close (should be within less than one minute) things start getting messy:
At first I get exceptions that the Server did not respond within the specified timeout interval, then all hell breaks lose:
ORA 01041 (internal error), 12536 (operation would block), 12560 (TNS protocol adapter), 12650 (encryption and data integrity) are thrown seemingly randomly. It's usually not all of the above mentioned error codes, but most of them;
I don't care that much about those error codes (at least not in this sample context) - the problem is that several seconds after those errors start occuring, I get an unhandled Exception:
With Devart 7.7.226 I get the following:
Code: Select all
Unhandled Exception: System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
at OciDynamicType.nativeOCIHandleFree(HandleRef , Int32 )
at OciDynamicType.OCIHandleFree(HandleRef , Int32 )
at Devart.Data.Oracle.ay.c()
at Devart.Data.Oracle.ao.c()
at Devart.Data.Oracle.OracleInternalConnection.a(Boolean A_0)
at Devart.Common.DbConnectionInternal.CloseInternalConnection()
at Devart.Common.DbConnectionInternal.Close()
at Devart.Common.DbConnectionBase.Close()
Code: Select all
Exception Info: System.Runtime.InteropServices.SEHException
Stack:
at OciDynamicType.nativeOCIHandleFree(System.Runtime.InteropServices.HandleRef, Int32)
at OciDynamicType.nativeOCIHandleFree(System.Runtime.InteropServices.HandleRef, Int32)
at OciDynamicType.OCIHandleFree(System.Runtime.InteropServices.HandleRef, Int32)
at Devart.Data.Oracle.bf.b(System.Object)
at System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)
at System.Threading.ThreadHelper.ThreadStart(System.Object)
Can you please take a look at this issue and provide a bugfix and/or a workaround to resolve this? If you have any problem reproducing the error feel free to use my sample (see below) or ask.
Looking forward to hear from you,
Klaus
Here's the sample I ran in a .NET 4.5 console application (x86 and x64)
Code: Select all
using System;
using System.Threading;
using System.Threading.Tasks;
using Devart.Data.Oracle;
namespace Samples.MemoryTest
{
class SimpleMemoryTest
{
private const string ConnectionStringTemplate = "Data Source=TNSNAME;User ID=YOURUSER;Password=YOURPASS;Unicode=True;Pooling=False";
private const int NumberOfParallelExecutions = 90;
private static string connectionString;
private static int countGlobalOpen = 0;
static void Main(string[] args)
{
Console.WriteLine("Will start {0} tasks that run parallel and that'll just open and close the connection", NumberOfParallelExecutions);
ShowDevArtVersion();
RegisterGlobalExceptions();
//Make sure that pooling is enabled, whatever the connection String says;
OracleConnectionStringBuilder csb = new OracleConnectionStringBuilder(ConnectionStringTemplate);
csb.Pooling = false;
connectionString = csb.ConnectionString;
for (int i = 0; i < NumberOfParallelExecutions; i++)
{
int currentInstanceNumber = i;
Task suite = new Task(() => StartTestSuite(currentInstanceNumber), TaskCreationOptions.PreferFairness);
suite.Start();
}
Console.WriteLine("Tasks started - we'll see what happens");
Console.ReadLine();
}
private static void StartTestSuite(int currentInstanceNumber)
{
Console.WriteLine("Task {0} started OpenAndClose", currentInstanceNumber);
int countInstanceOpen = 0;
while (true)
{
try
{
using (OracleConnection connection = new OracleConnection(connectionString))
{
connection.Open();
#region Some logging
countInstanceOpen++;
if (countInstanceOpen % 100 == 0)
{
Console.WriteLine("Task {0} opened {1} times", currentInstanceNumber, countInstanceOpen);
}
Interlocked.Increment(ref countGlobalOpen);
if (countGlobalOpen % 1000 == 0)
{
Console.WriteLine("All tasks openend {0} times", countGlobalOpen);
}
#endregion
connection.Close();
}
}
catch (Exception ex)
{
Console.WriteLine("Ex after {0} task, {1} global connections: {2}", countInstanceOpen, countGlobalOpen, ex.Message);
}
}
}
private static void RegisterGlobalExceptions()
{
AppDomain.CurrentDomain.UnhandledException += CurrentDomainOnUnhandledException;
}
private static void CurrentDomainOnUnhandledException(object sender, UnhandledExceptionEventArgs unhandledExceptionEventArgs)
{
ShowDevArtVersion();
if (unhandledExceptionEventArgs.IsTerminating)
{
Console.WriteLine("Can't recover from and can't handle UnhandledDomainException {0}");
}
else
{
Console.WriteLine("Unhandled Domain Exception : {0}", unhandledExceptionEventArgs.ExceptionObject);
}
}
private static void ShowDevArtVersion()
{
Console.WriteLine("Using Devart Version {0}", typeof(OracleConnection).Assembly.GetName().Version);
Console.WriteLine("(Check bindind redirect in app.config if this is not the desired version");
}
}
}