.Net Finalizer Order / Semantics in Esent and Ravendb
- by mattcodes
Help me understand. I've read that
"The time and order of execution of finalizers cannot be predicted or pre-determined"
Correct?
However looking at RavenDB source code TransactionStorage.cs I see this
~TransactionalStorage()
{
try
{
Trace.WriteLine(
"Disposing esent resources from finalizer! You should call TransactionalStorage.Dispose() instead!");
Api.JetTerm2(instance, TermGrbit.Abrupt);
}
catch (Exception exception)
{
try
{
Trace.WriteLine("Failed to dispose esent instance from finalizer because: " + exception);
}
catch
{
}
}
}
The API class (which belongs to Managed Esent) which presumable takes handles on native resources presumably using a SafeHandle?
So if I understand correctly the native handles SafeHandle can be finalized before TransactionStorage which could have undesired effects, perhaps why Ayende has added an catch all clause around this?
Actually diving into Esent code, it does not use SafeHandles.
According to CLR via C# this is dangerous?
internal static class SomeType {
[DllImport("Kernel32", CharSet=CharSet.Unicode, EntryPoint="CreateEvent")]
// This prototype is not robust
private static extern IntPtr CreateEventBad(
IntPtr pSecurityAttributes, Boolean manualReset, Boolean initialState, String name);
// This prototype is robust
[DllImport("Kernel32", CharSet=CharSet.Unicode, EntryPoint="CreateEvent")]
private static extern SafeWaitHandle CreateEventGood(
IntPtr pSecurityAttributes, Boolean manualReset, Boolean initialState, String name)
public static void SomeMethod() {
IntPtr handle = CreateEventBad(IntPtr.Zero, false, false, null);
SafeWaitHandle swh = CreateEventGood(IntPtr.Zero, false, false, null);
}
}
Managed Esent (NativeMEthods.cs) looks like this (using Ints vs IntPtrs?):
[DllImport(EsentDll, CharSet = EsentCharSet, ExactSpelling = true)]
public static extern int JetCreateDatabase(IntPtr sesid, string szFilename, string szConnect, out uint dbid, uint grbit);
Is Managed Esent handling finalization/dispoal the correct way, and second is RavenDB handling finalizer the corret way or compensating for Managed Esent?