Access Violation Exception in SqlCeConnection dispose
Asked Answered
T

1

7

Application/Code description:

My application is based on c# and uses SQL Server CE and iv'e got this exception only twice at the same code location. the crash with this exception was not introduced till this version. the only change in this version was changing the .net framework to 4.5.2.

I'm getting access violation exception on the dispose of an SqlCeConnection with the following error:

Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

This exception is not intercepted by the try catch clause of .net- it causes a crash.

In my code I use the following to run

try
{
    var connectionString = string.Format("{0}{1}{2}", "Data Source=", _localDB, ";File Mode=Read Write;Max Database Size=4000;Persist Security Info=False;");
    using (var sqlCeConnection = new SqlCeConnection(connectionString))
    {
        using (var sqlCeCommand = new SqlCeCommand())
        {
            sqlCeCommand.Connection = sqlCeConnection;
            sqlCeCommand.CommandText = "SELECT * FROM Application";
            sqlCeConnection.Open();
            var result = (string)sqlCeCommand.ExecuteScalar();
            isValid = !IsValid(result);
        }
    }
}
catch (Exception ex)
{
    _log.Error("exception", ex);
}

call stack for the first crash:

ntdll!ZwWaitForMultipleObjects+a 
KERNELBASE!WaitForMultipleObjectsEx+e8 
kernel32!WaitForMultipleObjectsExImplementation+b3 
kernel32!WerpReportFaultInternal+215 
kernel32!WerpReportFault+77 
kernel32!BasepReportFault+1f 
kernel32!UnhandledExceptionFilter+1fc 
ntdll! ?? ::FNODOBFM::`string'+2365 
ntdll!_C_specific_handler+8c 
ntdll!RtlpExecuteHandlerForException+d 
ntdll!RtlDispatchException+45a 
ntdll!KiUserExceptionDispatcher+2e 
sqlcese35!__SafeRelease+c 
sqlcese35!Column::`vector deleting destructor'+5c 
sqlcese35!Object::DeleteObjects+39 
sqlcese35!Table::`vector deleting destructor'+45 
sqlcese35!Table::Release+27 
sqlcese35!HashTable::~HashTable+2a 
sqlcese35!Store::~Store+12b 
sqlcese35!Store::Release+2a 
sqlceme35!ME_SafeRelease+17 
DomainBoundILStubClass.IL_STUB_PInvoke(IntPtr ByRef)+78 
[[InlinedCallFrame] (System.Data.SqlServerCe.NativeMethods.SafeRelease)] System.Data.SqlServerCe.NativeMethods.SafeRelease(IntPtrByRef) 
System.Data.SqlServerCe.SqlCeConnection.ReleaseNativeInterfaces()+147 
System.Data.SqlServerCe.SqlCeConnection.Dispose(Boolean)+f1 
System_ni!System.ComponentModel.Component.Dispose()+18 

call stack for the second crash:

ntdll!NtWaitForMultipleObjects+a 
KERNELBASE!WaitForMultipleObjectsEx+e8 
kernel32!WaitForMultipleObjectsExImplementation+b3 
kernel32!WerpReportFaultInternal+215 
kernel32!WerpReportFault+77 
kernel32!BasepReportFault+1f 
kernel32!UnhandledExceptionFilter+1fc 
ntdll! ?? ::FNODOBFM::`string'+2335 
ntdll!_C_specific_handler+8c 
ntdll!RtlpExecuteHandlerForException+d 
ntdll!RtlDispatchException+45a 
ntdll!KiUserExceptionDispatcher+2e 
<Unloaded_sqlcese35.dll>+7c88c 
<Unloaded_sqlceqp35.dll>+102790 
0x06ccc898 
0x06f9efc8 
0x1eca8018 
0x1f207400 
<Unloaded_sqlcese35.dll>+228dc 
0x00000004 
0x2edff008 
0x00000002 
0x00000003 
0x00000004 
<Unloaded_sqlcese35.dll>+3fbd9 
0x06ccc898 
DomainBoundILStubClass.IL_STUB_PInvoke(IntPtr ByRef)+78 
[[InlinedCallFrame] (System.Data.SqlServerCe.NativeMethods.SafeRelease)] System.Data.SqlServerCe.NativeMethods.SafeRelease(IntPtrByRef) 
System.Data.SqlServerCe.SqlCeConnection.ReleaseNativeInterfaces()+147 
System.Data.SqlServerCe.SqlCeConnection.Dispose(Boolean)+f1 
System_ni!System.ComponentModel.Component.Dispose()+1b 

I found some references on the internet that suggests some solutions:

  1. Probable solution: check multithreading issue on the same connection (attempted to read write protected memory. this is often an indication that other memory is corrupt)

    Rejection:
    a. the connection is created in the using brackets and doesn't get reused.
    b. the calling method is called every 5 minutes and verified via the dump file that it was not called simultaneously.

  2. Probable solution: sql ce version mismatch (http://blogs.msdn.com/b/sqlservercompact/archive/2009/05/06/troubleshooting-access-violation-exception-while-using-sql-server-compact-database-with-ado-net-provider.aspx)

    Probable Rejection: I can see in the version installed is 3.5 SP2 (3.5.8080.0) and from the modules located in the dump I can see the sqlceme35.dll, System.Data.SqlServerCe.dll DLL's are with version 3.05.8080.0

  3. Probable solution which is in question is the following: https://mcmap.net/q/129221/-attempted-to-read-or-write-protected-memory

    Probable Rejection: it doesn't sound right from a statistical perspective- the code crashed twice in the same place although there another place in the application code which writes and read to a different DB and the application didn't crash there.

  4. The last thing I was thinking about, may suggest a unload problem of DLLs (take a look at the second call stack). My guess is that the dll's are unloaded from the application while the application needed them in order to do a dispose, but it seams a bit blurry and a 'long shot'

My question is: what may cause the problem, and what is a probable solution?

Turner answered 31/8, 2015 at 8:47 Comment(9)
Do you try to share your SQL CE DB? For instance multiple users (processes) access the db on a shared location?Coquille
I would try to report it to M$ connect - connect.microsoft.com.Mafalda
C Sharper- no, the DB is not shared across processes, only the application process is accessing it.Turner
Why do you combine "SELECT *" with ExecuteScalar - just select the single value, please. I would try the latest SQL CE 3.5 SP2 build - erikej.blogspot.dk/2010/08/…Viv
Hi Erik, sorry for that i changed a column name when pasting the code to here (Legal issues prevention),Turner
I will try the latest SQL CE as you mentioned although i think of upgrading the DB to SQL CE 4Turner
Erik, one more question- if the SQL CE has a bug, that theoretically fixed in SQL CE 3.5 SP2, why would is this method the one that reproduces the issue? anyway, the changes on this build doesn't mention the specific access violation issue, which means that the problem will 'probably be fixed' until the issue will be reproduced again, which is very hard to do (non deterministic validation).Turner
You cannot catch AccessViolationException or any other corrupted state exception. This is a sign that something is seriously wrong, and the memory has already been corrupted. See this answer for a workaround. (The workaround should only be used for debugging, not production code.)Judicatory
Thanks 'theB', but since the issue is not reproduced easily (no at all now), i cannot use the workaround for advanced debugging.Turner
T
2

Although this solution is not yet verified, the solution is as follows:

From the second call stack i can see there is unload of native DLL's, my guess was that the dispose method of the SQL connection was using one of the methods it currently disposed. I verified thorough the Process dump that all the SqlCeConnection types were in the process of dispose.

Seeing ErikEj comment made me realize it's will be better if i will take a look in the code differences that was made between SQL-CE 3.5 to 4.0 (System.Data.SqlServerCe.dll).

after viewing the code, i could see that the method of the release was moved to a later position inside the dispose method.

In addition i could see that before calling SafeRelease there was another check that checks if the native DLLs that were needed for safe release was released already- and throw an exception.

bottom line, SQL-CE 4.0 has 2 solutions for the same issue.

my guess is that this issue was caused because of this.

the solution for now was to keep a connection during all the application life-cycle (which has no connection string), this cause the pointer pool to keep the native Dlls in the memory for all the application life-cycle.

the better solution is to move to SQL-CE 4.0 .

Turner answered 2/9, 2015 at 16:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.