コード例 #1
0
        private static void SerializeExceptionsForDump(Exception currentException, IntPtr exceptionCCWPtr, LowLevelList <byte[]> serializedExceptions)
        {
            const UInt32 NoInnerExceptionValue = 0xFFFFFFFF;

            // Approximate upper size limit for the serialized exceptions (but we'll always serialize currentException)
            // If we hit the limit, because we serialize in arbitrary order, there may be missing InnerExceptions or nested exceptions.
            const int MaxBufferSize = 20000;

            int nExceptions;

            RuntimeImports.RhGetExceptionsForCurrentThread(null, out nExceptions);
            Exception[] curThreadExceptions = new Exception[nExceptions];
            RuntimeImports.RhGetExceptionsForCurrentThread(curThreadExceptions, out nExceptions);
            LowLevelList <Exception> exceptions = new LowLevelList <Exception>(curThreadExceptions);
            LowLevelList <Exception> nonThrownInnerExceptions = new LowLevelList <Exception>();

            uint currentThreadId = Interop.mincore.GetCurrentThreadId();

            // Reset nesting levels for exceptions on this thread that might not be currently in flight
            foreach (ExceptionData exceptionData in s_exceptionDataTable.GetValues())
            {
                if (exceptionData.ExceptionMetadata.ThreadId == currentThreadId)
                {
                    exceptionData.ExceptionMetadata.NestingLevel = -1;
                }
            }

            // Find all inner exceptions, even if they're not currently being handled
            for (int i = 0; i < exceptions.Count; i++)
            {
                if (exceptions[i].InnerException != null && !exceptions.Contains(exceptions[i].InnerException))
                {
                    exceptions.Add(exceptions[i].InnerException);
                    nonThrownInnerExceptions.Add(exceptions[i].InnerException);
                }
            }

            int currentNestingLevel = curThreadExceptions.Length - 1;

            // Populate exception data for all exceptions interesting to this thread.
            // Whether or not there was previously data for that object, it might have changed.
            for (int i = 0; i < exceptions.Count; i++)
            {
                ExceptionData exceptionData = s_exceptionDataTable.GetOrCreateValue(exceptions[i]);

                exceptionData.ExceptionMetadata.ExceptionId = (UInt32)System.Threading.Interlocked.Increment(ref s_currentExceptionId);
                if (exceptionData.ExceptionMetadata.ExceptionId == NoInnerExceptionValue)
                {
                    exceptionData.ExceptionMetadata.ExceptionId = (UInt32)System.Threading.Interlocked.Increment(ref s_currentExceptionId);
                }

                exceptionData.ExceptionMetadata.ThreadId = currentThreadId;

                // Only include nesting information for exceptions that were thrown on this thread
                if (!nonThrownInnerExceptions.Contains(exceptions[i]))
                {
                    exceptionData.ExceptionMetadata.NestingLevel = currentNestingLevel;
                    currentNestingLevel--;
                }
                else
                {
                    exceptionData.ExceptionMetadata.NestingLevel = -1;
                }

                // Only match the CCW pointer up to the current exception
                if (Object.ReferenceEquals(exceptions[i], currentException))
                {
                    exceptionData.ExceptionMetadata.ExceptionCCWPtr = exceptionCCWPtr;
                }

                byte[] serializedEx = exceptions[i].SerializeForDump();
                exceptionData.SerializedExceptionData = serializedEx;
            }

            // Populate inner exception ids now that we have all of them in the table
            for (int i = 0; i < exceptions.Count; i++)
            {
                ExceptionData exceptionData;
                if (!s_exceptionDataTable.TryGetValue(exceptions[i], out exceptionData))
                {
                    // This shouldn't happen, but we can't meaningfully throw here
                    continue;
                }

                if (exceptions[i].InnerException != null)
                {
                    ExceptionData innerExceptionData;
                    if (s_exceptionDataTable.TryGetValue(exceptions[i].InnerException, out innerExceptionData))
                    {
                        exceptionData.ExceptionMetadata.InnerExceptionId = innerExceptionData.ExceptionMetadata.ExceptionId;
                    }
                }
                else
                {
                    exceptionData.ExceptionMetadata.InnerExceptionId = NoInnerExceptionValue;
                }
            }

            int totalSerializedExceptionSize = 0;
            // Make sure we include the current exception, regardless of buffer size
            ExceptionData currentExceptionData = null;

            if (s_exceptionDataTable.TryGetValue(currentException, out currentExceptionData))
            {
                byte[] serializedExceptionData = currentExceptionData.Serialize();
                serializedExceptions.Add(serializedExceptionData);
                totalSerializedExceptionSize = serializedExceptionData.Length;
            }

            checked
            {
                foreach (ExceptionData exceptionData in s_exceptionDataTable.GetValues())
                {
                    // Already serialized currentException
                    if (currentExceptionData != null && exceptionData.ExceptionMetadata.ExceptionId == currentExceptionData.ExceptionMetadata.ExceptionId)
                    {
                        continue;
                    }

                    byte[] serializedExceptionData = exceptionData.Serialize();
                    if (totalSerializedExceptionSize + serializedExceptionData.Length >= MaxBufferSize)
                    {
                        break;
                    }

                    serializedExceptions.Add(serializedExceptionData);
                    totalSerializedExceptionSize += serializedExceptionData.Length;
                }
            }
        }