Linky
Linky

Reputation: 604

Can the Stacktrace of an AccessViolationException be trusted

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

Answers (2)

Hans Passant
Hans Passant

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

Fab
Fab

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):

  • Bad use of an unmanaged dependency
  • Bad use of GCHandle
  • Buggy unsafe code

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

Related Questions