runtime: Unhandled exception at 0x77256214 (ntdll.dll) in My.exe: 0xC0000374: A heap has been corrupted (parameters: 0x77272378).
I have a long-running .NET console application (4.6.1). Suddenly since fews days I am getting this error in Visual Studio,
Unhandled exception at 0x77256214 (ntdll.dll) in My.exe: 0xC0000374: A heap has been corrupted (parameters: 0x77272378).
Pressing F5 again, it shows me another stuck and then stuck with the same error,
Exception thrown at 0x771B234D (ntdll.dll) in My.exe: 0xC0000005: Access violation reading location 0x656C6573.
I have global try catch which is not triggering in the console application. I have added,
<legacyCorruptedStateExceptionsPolicy enabled="true" /> and [HandleProcessCorruptedStateExceptionsAttribute] but still application crashes without hitting the breakpoint. Then I tried WinDBG (.loadby sos clr then !analyze -v then !CLRStack -a then !dumpstackobjects),
OS Thread Id: 0x3da4 (0)
Child SP IP Call Site
007cea38 771ac33c [GCFrame: 007cea38]
007cea54 771ac33c [HelperMethodFrame_1OBJ: 007cea54] System.Threading.Monitor.ReliableEnter(System.Object, Boolean ByRef)
007cead0 60f98710 System.Collections.Hashtable+SyncHashtable.Remove(System.Object) [f:\dd\ndp\clr\src\BCL\system\collections\hashtable.cs @ 1518]
007ceafc 0db7405f Oracle.DataAccess.Client.OracleResourcePool.RemoveResourceHolder(Oracle.DataAccess.Client.OracleResourceHolder)
007ceb28 0db73ffd Oracle.DataAccess.Client.OracleResourceHolder.Dispose()
007ceb34 0db7386f Oracle.DataAccess.Client.OracleResourceHolder.TransactionCompleted(System.Object, System.Transactions.TransactionEventArgs)
007ceb38 0086e053 [InlinedCallFrame: 007ceb38]
007cebb0 0086e053 [MulticastFrame: 007cebb0] System.Transactions.TransactionCompletedEventHandler.Invoke(System.Object, System.Transactions.TransactionEventArgs)
007cebdc 556cc0fb System.Transactions.InternalTransaction.FireCompletion()
007cebf0 556ea3f2 System.Transactions.TransactionStatePromotedAborted.EnterState(System.Transactions.InternalTransaction)
007cec08 556ed9c0 System.Transactions.TransactionStateDelegatedAborting.ChangeStatePromotedAborted(System.Transactions.InternalTransaction)
007cec14 556ee8ba System.Transactions.DurableEnlistmentDelegated.Aborted(System.Transactions.InternalEnlistment, System.Exception)
007cec24 556e34d6 System.Transactions.SinglePhaseEnlistment.Aborted()
007cec6c 0e36d662 Oracle.DataAccess.Client.PromotableTxnMgr.Rollback(System.Transactions.SinglePhaseEnlistment)
007cec90 556ed922 System.Transactions.TransactionStateDelegatedAborting.EnterState(System.Transactions.InternalTransaction)
007cecd4 556eb8f5 System.Transactions.TransactionStateDelegated.Rollback(System.Transactions.InternalTransaction, System.Exception)
007cece4 556c9c0a System.Transactions.Transaction.Rollback()
007ced18 556f0f43 System.Transactions.TransactionScope.InternalDispose()
007ced50 556f0da7 System.Transactions.TransactionScope.Dispose()
007cee04 0d49f9ae MyApp.Program.method()
Clearly, it’s related to TransactionScope and Oracle but dunno why its crashing. For now I am just looking for a work around
About this issue
- Original URL
- State: closed
- Created 5 years ago
- Comments: 16 (9 by maintainers)
As you know, when the code leaves the “using” statement block for the TransactionScope, the TransactionScope.Dispose method is invoked.
If the code inside the “using” block has not yet called “scope.Complete()”, the TransactionScope.Dispose method assumes that not all of the code inside the “using” block successfully executed, so the transaction must be aborted. Typically the “scope.Complete()” statement would be the last statement before the ending brace “}” of the “using” statement block, like this:
using(TransactionScope scope = new TransactionScope()) { // Our Code scope.Complete(); }
Since the scope was not completed, it forces the abort/rollback of the transaction and then also attempts to notify any delegates for the Transaction.TransactionCompleted event to let them know that the outcome of the transaction is “aborted”. That is why you see the System.Transactions.InternalTransaction.FireCompletion method on the stack. The Oracle code must have registered a delegate for the Transaction.TransactionCompleted event using the method Oracle.DataAccess.Client.OracleResourceHolder.TransactionCompleted as the delegate.
The heap corruption is apparently detected during the processing in the Oracle code.
I am wondering if the “using” using block actually encountered some exception that prevented it from calling “scope.Complete()”, but that exception is being masked by another exception that occurs during the TransactionCompleted processing which is happening “inline” in this case.
Maybe if you put a try…catch(Exception) inside the “using” block, with the “catch” just before the end of the “using” block. Then you might catch the “original” exception (if my theory is correct). The catch block should then rethrow the exception. Like this:
using(TransactionScope scope = new TransactionScope()) { try { // Our Code scope.Complete(); } catch (Exception ex) { // Do something you might want to do. throw; } }
I don’t have any insight into what that Oracle code is doing other than what is on the stack. I think further investigation needs to start with Oracle. If it comes back that indicates that System.Transactions may have corrupted something, then please re-raise to our attention.
@imranbaloch,
What exception are you seeing for “ex1”, where you set “commit” to false? Does that exception type vary when you see the process crash? Or is there some sort of pattern that might indicate a different between the crashing and non-crashing scenarios?
I am not sure we are going to get to the bottom of this until we get some information from your request to Oracle, as that’s where the crash is happening.
Jim
I am not able to answer your questions about the process crashing issue, but will continue to try to address the System.Transactions questions.
What I gather from your last message is that your “using (TransactionScope)” block does, in fact, include a “scope.Complete()” call, but that call is not executing. And you are not seeing an exception? Or you are not able catch the exception? The TransactionScope.Dispose will execute even if there was an exception thrown from within the “using” block. I believe because the process crashing is due to something in the Oracle code during the processing of TransactionCompleted event which is invoked during TransactionScope.Dispose, you don’t get to see what exception is happening inside the TransactionScope using block. That is why I suggested the try…catch within the using block. That catch should execute BEFORE TransactionScope.Dispose is invoked, so you should be able to see the “original” exception. Of course, maybe that is less interesting to you than why the Oracle code is causing the process to crash.