3

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)

Linky
  • 605
  • 8
  • 24
  • There are no absolute guarantees when you get an access violation. Undefined behavior occurred. Depending on *how* it occurred, you may or may not get a reliable stack trace. – jalf Sep 25 '15 at 07:55
  • I would recommend moving managed code in different process and use REST Call from your managed process over HTTP, you can do logging in your unmanaged code, and if everything is hosted in IIS, IIS can easily kill and restart worker process if it failed for any reason. – Akash Kava Oct 01 '15 at 05:49

2 Answers2

4

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);   
            }
        }
    }
Community
  • 1
  • 1
Fab
  • 14,327
  • 5
  • 49
  • 68
2

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.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536