[corlib] StackTrace fixes.
authorMarcos Henrich <marcos.henrich@xamarin.com>
Thu, 7 Jul 2016 16:57:04 +0000 (17:57 +0100)
committerMarcos Henrich <marcos.henrich@xamarin.com>
Fri, 8 Jul 2016 21:45:49 +0000 (22:45 +0100)
Replaced static constructor with delayed initialization.

Fixed possible undeterministic order of dumped MVIDs.

Used AppendFormat when possible.

Added comment to StackTrace.AddMetadataHandler explaining that it can be
used with reflection by outside code, to avoid removing it or changing
its signature.

Added StringComparer.Ordinal to dictionary.

mcs/class/corlib/System.Diagnostics/StackTrace.cs

index 69c2c6f02f0bfd91e344c0b002962bac499e52cc..64f3eef4814a0e8a76e7fd4aa3e585f5dc9ef363 100644 (file)
@@ -63,13 +63,6 @@ namespace System.Diagnostics {
 
                private static Dictionary<string, Func<StackTrace, string>> metadataHandlers;
 
-               static StackTrace ()
-               {
-                       metadataHandlers = new Dictionary<string, Func<StackTrace, string>> ();
-
-                       InitMetadataHandlers ();
-               }
-
                [MethodImplAttribute (MethodImplOptions.NoInlining)]
                public StackTrace ()
                {
@@ -314,13 +307,16 @@ namespace System.Diagnostics {
 
                void AddMetadata (StringBuilder sb)
                {
+                       if (metadataHandlers == null)
+                               InitMetadataHandlers ();
+
                        foreach (var handler in metadataHandlers) {
                                var lines = handler.Value (this);
                                using (var reader = new StringReader (lines)) {
                                        string line;
                                        while ((line = reader.ReadLine()) != null) {
                                                sb.AppendLine ();
-                                               sb.Append (string.Format ("[{0}] {1}", handler.Key, line));
+                                               sb.AppendFormat ("[{0}] {1}", handler.Key, line);
                                        }
                                }
                        }
@@ -334,6 +330,8 @@ namespace System.Diagnostics {
 
                static void InitMetadataHandlers ()
                {
+                       metadataHandlers = new Dictionary<string, Func<StackTrace, string>> (StringComparer.Ordinal);
+
                        string aotid = Assembly.GetAotId ();
                        if (aotid != null)
                                AddMetadataHandler ("AOTID", st => { return aotid; });
@@ -346,24 +344,35 @@ namespace System.Diagnostics {
                                        if (method == null)
                                                continue;
                                        var mvid = method.Module.ModuleVersionId;
-                                       if (!mvidLines.ContainsKey (mvid))
-                                               mvidLines.Add (mvid, new List<int> ());
 
-                                       mvidLines[mvid].Add (lineNumber);
+                                       List<int> lines = null;
+                                       if (!mvidLines.TryGetValue (mvid, out lines)) {
+                                               lines = new List<int> ();
+                                               mvidLines.Add (mvid, lines);
+                                       }
+
+                                       lines.Add (lineNumber);
                                }
 
+                               var mvids = new List<Guid> (mvidLines.Keys);
+                               mvids.Sort ();
+
                                var sb = new StringBuilder ();
-                               foreach (var kv in mvidLines) {
-                                       var mvid = kv.Key.ToString ().ToUpper ();
-                                       sb.AppendLine (string.Format ("{0} {1}", mvid, string.Join (",", kv.Value)));
+                               foreach (var mvid in mvids) {
+                                       var mvidStr = mvid.ToString ().ToUpper ();
+                                       sb.AppendLine (string.Format ("{0} {1}", mvid, string.Join (",", mvidLines[mvid])));
                                }
 
                                return sb.ToString ();
                        });
                }
 
+               // This method signature should not change, apps can use it with reflection to add custom metadata handlers.
                private static void AddMetadataHandler (string id, Func<StackTrace, string> handler)
                {
+                       if (metadataHandlers == null)
+                               InitMetadataHandlers ();
+
                        metadataHandlers.Add (id, handler);
                }
        }