Fix order of raising AssemblyLoadContext.Unloading and AppDomain.ProcessExit (#8737)
authorCaio Kinelski <t-cakine@microsoft.com>
Wed, 28 Dec 2016 16:11:05 +0000 (08:11 -0800)
committerKoundinya Veluri <kouvel@microsoft.com>
Wed, 28 Dec 2016 16:11:05 +0000 (08:11 -0800)
The AssemblyLoadContext.Unloading event must be raised before the AppDomain.ProcessExit event.
AssemblyLoadContext.OnUnloading now subscribes to AppContext.Unloading.
Then AppContext.OnAppContextUnloading and AppContext.OnProcessExit, in that order, subscribe to AppDomain.ProcessExit.
Part of fix for dotnet/corefx#14566

src/mscorlib/src/System/AppContext/AppContext.cs
src/mscorlib/src/System/Runtime/Loader/AssemblyLoadContext.cs

index 41e4450..e318f93 100644 (file)
@@ -19,6 +19,16 @@ namespace System
         }
         private static readonly Dictionary<string, SwitchValueState> s_switchMap = new Dictionary<string, SwitchValueState>();
 
+        static AppContext()
+        {
+            // Unloading event must happen before ProcessExit event
+            AppDomain.CurrentDomain.ProcessExit += OnUnloading;
+            AppDomain.CurrentDomain.ProcessExit += OnProcessExit;
+
+            // populate the AppContext with the default set of values
+            AppContextDefaultValues.PopulateDefaultValues();
+        }
+
         public static string BaseDirectory
         {
             get
@@ -73,25 +83,28 @@ namespace System
             }  
         }  
 
-        public static event System.EventHandler ProcessExit
-        {  
-            add  
-            {  
-                AppDomain.CurrentDomain.ProcessExit += value;  
-            }  
-            remove  
-            {  
-                AppDomain.CurrentDomain.ProcessExit -= value;  
-            }  
+        public static event System.EventHandler ProcessExit;
+        public static event System.EventHandler Unloading;
+
+        private static void OnProcessExit(object sender, EventArgs e)
+        {
+            var processExit = ProcessExit;
+            if (processExit != null)
+            {
+                processExit(null, EventArgs.Empty);
+            }
         }
 
-        #region Switch APIs
-        static AppContext()
+        private static void OnUnloading(object sender, EventArgs e)
         {
-            // populate the AppContext with the default set of values
-            AppContextDefaultValues.PopulateDefaultValues();
+            var unloading = Unloading;
+            if (unloading != null)
+            {
+                unloading(null, EventArgs.Empty);
+            }
         }
 
+        #region Switch APIs
         /// <summary>
         /// Try to get the value of the switch.
         /// </summary>
index e158a5a..ee9861f 100644 (file)
@@ -75,7 +75,7 @@ namespace System.Runtime.Loader
             // Since unloading an AssemblyLoadContext is not yet implemented, this is a temporary solution to raise the
             // Unloading event on process exit. Register for the current AppDomain's ProcessExit event, and the handler will in
             // turn raise the Unloading event.
-            AppDomain.CurrentDomain.ProcessExit += OnProcessExit;
+            AppContext.Unloading += OnAppContextUnloading;
         }
 
         [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
@@ -446,7 +446,7 @@ namespace System.Runtime.Loader
 #endif // FEATURE_MULTICOREJI
         }
 
-        private void OnProcessExit(object sender, EventArgs e)
+        private void OnAppContextUnloading(object sender, EventArgs e)
         {
             var unloading = Unloading;
             if (unloading != null)