Reputation: 604
An AccessViolationException was thrown in one of our services. We registered AppDomain.CurrentDomain.UnhandledException
and from the event we got below call stack. The event was raised three times within 2 seconds on three different threads and has the exact same stack. So everything should be clear
On the other hand - the correlating log entry in windows event log shows no stack at all. Our application uses unmanaged libraries as well and my guess would've been that the exception is caused by misusing them (for example oci) rather than the managed stack shown.
Can I trust that the stack reported is the stack that's causing the problem - or is this just an educated guess?
System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
at System.Linq.EnumerableSorter`2.ComputeKeys(TElement[] elements, Int32 count)
at System.Linq.EnumerableSorter`1.Sort(TElement[] elements, Int32 count)
at System.Linq.OrderedEnumerable`1.<GetEnumerator>d__0.MoveNext()
at System.Linq.Enumerable.<TakeIterator>d__3a`1.MoveNext()
at System.Data.Services.QueryResultInfo.MoveNext()
at System.Data.Services.DataService`1.SerializeResponseBody(RequestDescription description, IDataService dataService, IODataResponseMessage responseMessage)
at System.Data.Services.DataService`1.HandleRequest()
at System.Data.Services.DataService`1.ProcessRequestForMessage(Stream messageBody)
at SyncInvokeProcessRequestForMessage(Object , Object[] , Object[] )
at System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(Object instance, Object[] inputs, Object[]& outputs)
at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage31(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)
at System.ServiceModel.Dispatcher.ChannelHandler.DispatchAndReleasePump(RequestContext request, Boolean cleanThread, OperationContext currentOperationContext)
at System.ServiceModel.Dispatcher.ChannelHandler.HandleRequest(RequestContext request, OperationContext currentOperationContext)
at System.ServiceModel.Dispatcher.ChannelHandler.AsyncMessagePump(IAsyncResult result)
at System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(IAsyncResult result)
at System.Runtime.AsyncResult.Complete(Boolean completedSynchronously)
at System.Runtime.InputQueue`1.AsyncQueueReader.Set(Item item)
at System.Runtime.InputQueue`1.EnqueueAndDispatch(Item item, Boolean canDispatchOnThisThread)
at System.Runtime.InputQueue`1.EnqueueAndDispatch(T item, Action dequeuedCallback, Boolean canDispatchOnThisThread)
at System.ServiceModel.Channels.SingletonChannelAcceptor`3.Enqueue(QueueItemType item, Action dequeuedCallback, Boolean canDispatchOnThisThread)
at System.ServiceModel.Channels.HttpPipeline.EnqueueMessageAsyncResult.CompleteParseAndEnqueue(IAsyncResult result)
at System.ServiceModel.Channels.HttpPipeline.EnqueueMessageAsyncResult.HandleParseIncomingMessage(IAsyncResult result)
at System.Runtime.AsyncResult.SyncContinue(IAsyncResult result)
at System.ServiceModel.Channels.HttpPipeline.EmptyHttpPipeline.BeginProcessInboundRequest(ReplyChannelAcceptor replyChannelAcceptor, Action dequeuedCallback, AsyncCallback callback, Object state)
at System.ServiceModel.Channels.HttpChannelListener`1.HttpContextReceivedAsyncResult`1.ProcessHttpContextAsync()
at System.ServiceModel.Channels.HttpChannelListener`1.BeginHttpContextReceived(HttpRequestContext context, Action acceptorCallback, AsyncCallback callback, Object state)
at System.ServiceModel.Channels.SharedHttpTransportManager.EnqueueContext(IAsyncResult listenerContextResult)
at System.ServiceModel.Channels.SharedHttpTransportManager.OnGetContextCore(IAsyncResult listenerContextResult)
at System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(IAsyncResult result)
at System.Net.LazyAsyncResult.Complete(IntPtr userToken)
at System.Net.ListenerAsyncResult.IOCompleted(ListenerAsyncResult asyncResult, UInt32 errorCode, UInt32 numBytes)
at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)
As a remark: Guessing from the Exception code in the windows event log I think that it's a "real" windows AccessViolationException (0xc000005) and not a throw new AccessViolationException
(0xe043452)
Upvotes: 3
Views: 899
Reputation: 942050
The source code for the method at the top of the stack trace is readily available. You can tell which specific statement is most likely for the crash:
keys = new TKey[count];
That sets off code that you cannot see in the stack trace, you only get a dump of the managed code stack frames. So, yeah, it is reliable and the AVE is a "hard" one thrown by the processor, it just doesn't show you everything.
You'd need a minidump of the crashed process to see more. Not that this actually helps you at all, of course the code that crashed was not responsible for the crash. It is also not the kind of crash that repeats well, make small changes to the code or have it process different data and it might well be another new operator call that falls over.
Our application uses unmanaged libraries as well
That saves me having to explain to look for unmanaged code that may corrupt the GC heap. Don't expect to accomplish anything for the next month or so, sorry.
Upvotes: 2
Reputation: 14813
Does the stacktrace of an AccessViolationException indicate the code responsible for the access violation? The answer is No.
It just shows which call detected the Access Violation. Subsequent calls will fail and in fact the whole application will die because AccessViolationException
is not catchable by default and you should not catch it.
It means the memory was corrupted by some of these (not exhaustive list):
Your guess about a potential misuse of unmanaged dependencies is probably the root cause of the AccessViolationException.
Keep in mind that memory corruption is not deterministic: Even if it is occurring, it's not always detected by the runtime.
The following code is a way to get AccessViolationException
in Console.WriteLine()
. However it can also raise ExecutionEngineException
.
class Program
{
static void Main(string[] args)
{
AppDomain.CurrentDomain.UnhandledException += OnUnhandledException;
Thread.CurrentThread.Name = "Main";
ThreadPool.QueueUserWorkItem(Corrupt, Thread.CurrentThread);
ThreadPool.QueueUserWorkItem(RunMethod);
Console.ReadLine();
}
private static void OnUnhandledException(object sender, UnhandledExceptionEventArgs e)
{
Console.WriteLine(e.ExceptionObject);
}
private static void Corrupt(object state)
{
unsafe
{
var thread = (Thread)state;
fixed (char* str = thread.Name)
{
char* increment = str;
char* decrement = str;
while (true)
{
*(decrement--) = 'f';
*(increment++) = 'b';
Thread.Sleep(10);
}
}
}
}
[HandleProcessCorruptedStateExceptions ]
public static void RunMethod(object state)
{
try
{
while (true)
{
Console.WriteLine("I'm Alive");
Thread.Sleep(5000);
}
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
}
Upvotes: 4