Just recently my app has been inconsistently throwing a variety of exceptions like these:
Unable to cast object of type 'System.Threading.Thread' to type 'System.Transactions.SafeIUnknown'.
Unable to cast object of type 'System.Diagnostics.Process' to type 'System.Transactions.SafeIUnknown'.
Unable to cast object of type 'System.Drawing.SolidBrush' to type 'System.Transactions.SafeIUnknown'.
Unable to cast object of type 'System.Threading.Thread' to type 'System.Xml.Linq.XNamespace'.
(the last one might be a secondary effect of the others)
Stack traces of some of these are pasted below but note that all of them have these 3 final steps:
at System.Transactions.Transaction.JitSafeGetContextTransaction(ContextData contextData)
at System.Transactions.Transaction.FastGetTransaction(TransactionScope currentScope, ContextData contextData, Transaction& contextTransaction)
at System.Transactions.Transaction.get_Current()
Observations - these exceptions:
- Occur frequently, but not all the time (50%?)
- Don't always produce the same exception when they do occur
- Have no obvious connection to the code in my app which leads to them
- Are reproducible on various PCs
- Can't be found exactly in any searches I've done
The app is a set of C# DLLs called via COM from older VB6 code. However that has been in place for years, and we haven't changed anything about how that is done recently.
It is not a multi-threaded app, so the casts involving System.Threading.Thread
seem out of place. There was one third party module that used threads, but we took it out as an experiment: doing so did not resolve the problem but seemed to reduce the frequency of errors. This leads me to think its some kind of resource clobbering problem.
I am looking for advice such as:
If you've actually seen this pattern of exceptions before, what was the cause?
Recommendations for how to go about debugging the root issue
Example stack traces:
Unable to cast object of type 'System.Threading.Thread' to type 'System.Transactions.SafeIUnknown'.
at System.Transactions.Transaction.JitSafeGetContextTransaction(ContextData contextData)
at System.Transactions.Transaction.FastGetTransaction(TransactionScope currentScope, ContextData contextData, Transaction& contextTransaction)
at System.Transactions.Transaction.get_Current()
at System.Data.SQLite.SQLiteConnection.Open()
at Company.ABC.WrappedDbConnection.Open()
at Company.ABC.Program.DoSomething()
and
Unable to cast object of type 'System.Threading.Thread' to type 'System.Transactions.SafeIUnknown'.
at System.Transactions.Transaction.JitSafeGetContextTransaction(ContextData contextData)
at System.Transactions.Transaction.FastGetTransaction(TransactionScope currentScope, ContextData contextData, Transaction& contextTransaction)
at System.Transactions.Transaction.get_Current()
at System.Data.Common.ADP.IsSysTxEqualSysEsTransaction()
at System.Data.Common.ADP.NeedManualEnlistment()
at System.Data.OleDb.OleDbConnection.Open()
at Company.ABC.WrappedDbConnection.Open()
at Company.ABC.Program.DoSomething()
and
System.InvalidCastException: Unable to cast object of type 'System.Drawing.SolidBrush' to type 'System.Transactions.SafeIUnknown'.
at System.Transactions.Transaction.JitSafeGetContextTransaction(ContextData contextData)
at System.Transactions.Transaction.FastGetTransaction(TransactionScope currentScope, ContextData contextData, Transaction& contextTransaction)
at System.Transactions.Transaction.get_Current()
at System.Data.Common.ADP.IsSysTxEqualSysEsTransaction()
at System.Data.Common.ADP.NeedManualEnlistment()
at System.Data.OleDb.OleDbConnection.Open()
at Company.ABC.WrappedDbConnection.Open()
at Company.ABC.Program.DoSomething()
EDIT:
I tried looking into this using windbg (with SOS extensions for managed code).
It was able to break on the exception. Here is the stack trace from that point:
0:000> !DumpStack
OS Thread Id: 0x2d44 (0)
Current frame: KERNELBASE!RaiseException+0x62
ChildEBP RetAddr Caller, Callee
0019b658 750325f2 KERNELBASE!RaiseException+0x62, calling ntdll!RtlRaiseException
0019b688 774a7310 ntdll!RtlFreeHeap+0x1e0, calling ntdll!RtlFreeHeap+0x560
0019b69c 70a9f09f clr+0xf09f, calling KERNEL32!TlsGetValue
0019b6ac 70b928f1 clr!GetMetaDataPublicInterfaceFromInternal+0x9741, calling KERNELBASE!RaiseException
0019b6ec 70aae56d clr!LogHelp_NoGuiOnAssert+0x2add, calling clr!LogHelp_NoGuiOnAssert+0x2a92
0019b6f8 70aae50f clr!LogHelp_NoGuiOnAssert+0x2a7f
0019b748 70bfc1a2 clr!CreateApplicationContext+0x1c2d2, calling clr!GetMetaDataPublicInterfaceFromInternal+0x95b6
0019b77c 70e3d369 clr!CreateHistoryReader+0x72069, calling clr!CreateApplicationContext+0x1c279
0019b7dc 70bc6a59 clr!PreBindAssemblyEx+0x10959, calling clr+0xf7b0
0019b80c 09364844 (MethodDesc 08e0d5b4 +0x4c System.Transactions.Transaction.JitSafeGetContextTransaction(System.Transactions.ContextData)), calling clr!LogHelp_TerminateOnAssert+0x7f00
0019b83c 09362f2f (MethodDesc 08e0d5e4 +0x9f System.Transactions.Transaction.FastGetTransaction(System.Transactions.TransactionScope, System.Transactions.ContextData, System.Transactions.Transaction ByRef)), calling (MethodDesc 08e0d5b4 +0 System.Transactions.Transaction.JitSafeGetContextTransaction(System.Transactions.ContextData))
0019b850 09362510 (MethodDesc 08e0d5fc +0x78 System.Transactions.Transaction.get_Current()), calling (MethodDesc 08e0d5e4 +0 System.Transactions.Transaction.FastGetTransaction(System.Transactions.TransactionScope, System.Transactions.ContextData, System.Transactions.Transaction ByRef))
0019b86c 08ddf67a (MethodDesc 08e04c6c +0x14b2 System.Data.SQLite.SQLiteConnection.Open()), calling (MethodDesc 08e0d5fc +0 System.Transactions.Transaction.get_Current())
0019ba70 08ddd8ea (MethodDesc 08e058b0 +0x22 Company.ABC.WrappedDbConnection.Open()), calling 0dfce43a
This syncs with the CLR exception stacks that are above.
The thing I was mainly looking to ascertain is whether there is heap "corruption". But apparently not:
0:000> !VerifyHeap
No heap corruption detected.
So I think that rules out any of our native code (or 3rd party) simply wreaking havoc. But still no actual understanding of this problem. It looks more like a bug in the database layer to me.
This has been submitted as an issue here: https://developercommunity2.visualstudio.com/t/Unable-to-cast-object-of-type-varies/1241378