Update unloadability doc based on recent changes
authorJan Vorlicek <janvorli@microsoft.com>
Fri, 24 Apr 2020 12:56:29 +0000 (14:56 +0200)
committerJan Vorlicek <janvorli@microsoft.com>
Fri, 24 Apr 2020 12:56:29 +0000 (14:56 +0200)
The management of the handle that native runtime keeps to
AssemblyLoadContext has changed to fix a race recently, so I am updating
the doc according to the change.

docs/design/features/unloadability.md
docs/design/features/unloadability.svg

index 54a236c..4b61b0f 100644 (file)
@@ -98,8 +98,9 @@ The dashed lines represent indirect links from MethodTables of the objects to th
 ### First phase of unloading
 Unloading is initialized by the user code calling `AssemblyLoadContext.Unload` metod or by execution of the `AssemblyLoadContext` finalizer. The following steps are performed to start the unloading process.
 * The `AssemblyLoadContext` fires the `Unloading` event to allow the user code to perform cleanup if required (e.g. stop threads running inside of the context, remove references and destroy handles, etc.)
-* `AssemblyNative::PrepareForAssemblyLoadContextRelease` method is called, which in turn calls `CLRPrivBinderAssemblyLoadContext::PrepareForLoadContextRelease`
-* That method changes the handle referring to the `AssemblyLoadContext` to strong to keep the `AssemblyLoadContext` around until the unload is complete. For example, finalizers of types that are loaded into the `AssemblyLoadContext` may need access to the `AssemblyLoadContext`.
+* The `AssemblyLoadContext.InitiateUnload` method is called. It creates a strong GC handle referring to the `AssemblyLoadContext` to keep it around until the unload is complete. For example, finalizers of types that are loaded into the `AssemblyLoadContext` may need access to the `AssemblyLoadContext`.
+* Then it calls `AssemblyNative::PrepareForAssemblyLoadContextRelease` method with that strong handle as an argument, which in turn calls `CLRPrivBinderAssemblyLoadContext::PrepareForLoadContextRelease`
+* That method stores the passed in strong GC handle in `CLRPrivBinderAssemblyLoadContext::m_ptrManagedStrongAssemblyLoadContext`. 
 * Then it decrements refcount of the `AssemblyLoaderAllocator` the `CLRPrivBinderAssemblyLoadContext` points to.
 * Finally, it destroys the strong handle to the managed `LoaderAllocator`. That allows the `LoaderAllocator` to be collected.
 ### Second phase of unloading
@@ -109,5 +110,5 @@ This phase is initiated after all instances of types from assemblies loaded into
 * This method decrements reference count of all the `LoaderAllocators` that reference this `LoaderAllocator` and then the reference count of this `LoaderAllocator` itself.
 * If it was not the last reference, the native `AssemblyLoaderAllocator` must stay alive until there are no references to it, so there is nothing else to be done now. It will be destroyed later in `LoaderAllocator::GCLoaderAllocators` after the last reference goes away.
 * If we have released the last reference, the `LoaderAllocator::GCLoaderAllocators` is executed. This function finds all collectible LoaderAllocators that are not alive anymore and cleans up all domain assemblies in them. The cleanup removes each `DomainAssembly` from the `AppDomain` and also from the binding cache, it notifies debugger and finally destroys the `DomainAssembly`.
-* Strong handle to the managed `AssemblyLoadContext` in each of these LoaderAllocators is now destroyed. That enables these related AssemblyLoadContexts to be collected by GC.
-* Finally, these LoaderAllocators are registered for cleanup in the `AppDomain`. Their actual destruction happens on the finalizer thread in `Thread::DoExtraWorkForFinalizer`. When a `LoaderAllocator` is destroyed, the related `CLRPrivBinderAssemblyLoadContext` is destroyed too.
+* The strong and long weak handles to the managed `AssemblyLoadContext` in each of these LoaderAllocators are now destroyed. That enables these related `AssemblyLoadContext`s to be collected by GC.
+* Finally, these `LoaderAllocator`s are registered for cleanup in the `AppDomain`. Their actual destruction happens on the finalizer thread in `Thread::DoExtraWorkForFinalizer`. When a `LoaderAllocator` is destroyed, the related `CLRPrivBinderAssemblyLoadContext` is destroyed too.
index 52f39cd..2b361eb 100644 (file)
@@ -3,7 +3,7 @@
 <!-- Generated by Microsoft Visio, SVG Export Unloadability.svg Page-1 -->
 <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ev="http://www.w3.org/2001/xml-events"
                xmlns:v="http://schemas.microsoft.com/visio/2003/SVGExtensions/" width="8.11008in" height="7.55714in"
-               viewBox="0 0 583.926 544.114" xml:space="preserve" color-interpolation-filters="sRGB" class="st20">
+               viewBox="0 0 583.926 544.114" xml:space="preserve" color-interpolation-filters="sRGB" class="st19">
        <v:documentProperties v:langID="1033" v:viewMarkup="false">
                <v:userDefs>
                        <v:ud v:nameU="msvNoAutoConnect" v:val="VT0(1):26"/>
                .st9 {fill:#ffffff;stroke:none;stroke-linecap:butt;stroke-width:7.2}
                .st10 {fill:#000000;font-family:Calibri;font-size:0.666664em}
                .st11 {marker-end:url(#mrkr2-52);stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.75}
-               .st12 {fill:#ffffff;stroke:none;stroke-linecap:butt}
-               .st13 {marker-end:url(#mrkr2-125);stroke:#00b050;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.75}
-               .st14 {fill:#00b050;fill-opacity:1;stroke:#00b050;stroke-opacity:1;stroke-width:0.22935779816514}
-               .st15 {fill:none;stroke:none;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.75}
-               .st16 {fill:#000000;font-family:Calibri;font-size:1.00001em}
-               .st17 {stroke:#ffc000;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.75}
-               .st18 {fill:#ea700d;font-family:Calibri;font-size:1.00001em}
-               .st19 {fill:#0070c0;font-family:Calibri;font-size:1.00001em}
-               .st20 {fill:none;fill-rule:evenodd;font-size:12px;overflow:visible;stroke-linecap:square;stroke-miterlimit:3}
+               .st12 {marker-end:url(#mrkr2-125);stroke:#00b050;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.75}
+               .st13 {fill:#00b050;fill-opacity:1;stroke:#00b050;stroke-opacity:1;stroke-width:0.22935779816514}
+               .st14 {fill:none;stroke:none;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.75}
+               .st15 {fill:#000000;font-family:Calibri;font-size:1.00001em}
+               .st16 {stroke:#ffc000;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.75}
+               .st17 {fill:#ea700d;font-family:Calibri;font-size:1.00001em}
+               .st18 {fill:#0070c0;font-family:Calibri;font-size:1.00001em}
+               .st19 {fill:none;fill-rule:evenodd;font-size:12px;overflow:visible;stroke-linecap:square;stroke-miterlimit:3}
        ]]>
        </style>
 
@@ -43,7 +42,7 @@
                                markerUnits="strokeWidth" overflow="visible">
                        <use xlink:href="#lend2" transform="scale(-4.36,-4.36) "/>
                </marker>
-               <marker id="mrkr2-125" class="st14" v:arrowType="2" v:arrowSize="2" v:setback="4.36" refX="-4.36" orient="auto"
+               <marker id="mrkr2-125" class="st13" v:arrowType="2" v:arrowSize="2" v:setback="4.36" refX="-4.36" orient="auto"
                                markerUnits="strokeWidth" overflow="visible">
                        <use xlink:href="#lend2" transform="scale(-4.36,-4.36) "/>
                </marker>
                        <v:textBlock v:margins="rect(4,4,4,4)"/>
                        <v:textRect cx="33.1875" cy="535.114" width="42.9" height="17.6036"/>
                        <path d="M0 535.11 L63.1 535.11" class="st11"/>
-                       <rect v:rectContext="textBkgnd" x="16.6469" y="530.315" width="33.0815" height="9.59985" class="st12"/>
+                       <rect v:rectContext="textBkgnd" x="16.6469" y="530.315" width="33.0815" height="9.59985" class="st9"/>
                        <text x="16.65" y="537.51" class="st10" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Reference</text>             </g>
                <g id="shape26-106" v:mID="26" v:groupContext="shape" v:layerMember="0" transform="translate(111.051,-171.375)">
                        <title>Dynamic connector.26</title>
                        <v:textBlock v:margins="rect(4,4,4,4)"/>
                        <v:textRect cx="10.6875" cy="535.114" width="52.45" height="17.6036"/>
                        <path d="M9 544.11 L9 484.38" class="st11"/>
-                       <rect v:rectContext="textBkgnd" x="-10.6286" y="530.315" width="42.6324" height="9.59985" class="st12"/>
+                       <rect v:rectContext="textBkgnd" x="-10.6286" y="530.315" width="42.6324" height="9.59985" class="st9"/>
                        <text x="-10.63" y="537.51" class="st10" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Weak handle</text>          </g>
                <g id="shape27-113" v:mID="27" v:groupContext="shape" v:layerMember="0" transform="translate(188.676,-147.78)">
                        <title>Dynamic connector.27</title>
                        <v:textBlock v:margins="rect(4,4,4,4)"/>
                        <v:textRect cx="64.6875" cy="535.114" width="40" height="17.6036"/>
                        <path d="M0 535.11 L126.1 535.11" class="st11"/>
-                       <rect v:rectContext="textBkgnd" x="52.7677" y="530.315" width="23.8395" height="9.59985" class="st12"/>
+                       <rect v:rectContext="textBkgnd" x="52.7677" y="530.315" width="23.8395" height="9.59985" class="st9"/>
                        <text x="52.77" y="537.51" class="st10" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Pointer</text>               </g>
                <g id="shape28-120" v:mID="28" v:groupContext="shape" v:layerMember="0" transform="translate(318.051,-117.375)">
                        <title>Dynamic connector.28</title>
                        <desc>Pointer</desc>
                        <v:textBlock v:margins="rect(4,4,4,4)"/>
                        <v:textRect cx="-64.6875" cy="535.114" width="40" height="17.6036"/>
-                       <path d="M0 535.11 L-126.1 535.11" class="st13"/>
-                       <rect v:rectContext="textBkgnd" x="-76.6073" y="530.315" width="23.8395" height="9.59985" class="st12"/>
+                       <path d="M0 535.11 L-126.1 535.11" class="st12"/>
+                       <rect v:rectContext="textBkgnd" x="-76.6073" y="530.315" width="23.8395" height="9.59985" class="st9"/>
                        <text x="-76.61" y="537.51" class="st10" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Pointer</text>              </g>
                <g id="shape29-128" v:mID="29" v:groupContext="shape" v:layerMember="0" transform="translate(109.363,-108.375)">
                        <title>Dynamic connector.29</title>
                        <desc>Pointer</desc>
                        <v:textBlock v:margins="rect(4,4,4,4)"/>
                        <v:textRect cx="28.6875" cy="535.114" width="40" height="17.6036"/>
-                       <path d="M0 535.11 L54.1 535.11" class="st13"/>
+                       <path d="M0 535.11 L54.1 535.11" class="st12"/>
                        <rect v:rectContext="textBkgnd" x="16.7677" y="530.315" width="23.8395" height="9.59985" class="st9"/>
                        <text x="16.77" y="537.51" class="st10" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Pointer</text>               </g>
                <g id="shape31-142" v:mID="31" v:groupContext="shape" v:layerMember="0" transform="translate(386.676,-42)">
                        <title>Dynamic connector.31</title>
-                       <path d="M0 535.11 L45.1 535.11" class="st13"/>
+                       <path d="M0 535.11 L45.1 535.11" class="st12"/>
                </g>
-               <g id="shape32-147" v:mID="32" v:groupContext="shape" v:layerMember="0" transform="translate(471.051,-171.375)">
+               <g id="shape32-147" v:mID="32" v:groupContext="shape" v:layerMember="0" transform="translate(410.999,-171.375)">
                        <title>Dynamic connector.32</title>
-                       <desc>Handle (initially weak, strong during unload)</desc>
+                       <desc>Long weak handle</desc>
                        <v:textBlock v:margins="rect(4,4,4,4)"/>
-                       <v:textRect cx="9" cy="535.114" width="153.71" height="17.6036"/>
+                       <v:textRect cx="9.75102" cy="529.864" width="68.41" height="17.6036"/>
                        <path d="M9 544.11 L9 484.38" class="st11"/>
-                       <rect v:rectContext="textBkgnd" x="-62.9463" y="530.315" width="143.893" height="9.59985" class="st9"/>
-                       <text x="-62.95" y="537.51" class="st10" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Handle (initially weak, strong during unload)</text>                </g>
+                       <rect v:rectContext="textBkgnd" x="-19.5454" y="525.065" width="58.5931" height="9.59985" class="st9"/>
+                       <text x="-19.55" y="532.26" class="st10" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Long weak handle</text>             </g>
                <g id="shape33-154" v:mID="33" v:groupContext="shape" v:layerMember="0" transform="translate(273.613,-234.375)">
                        <title>Dynamic connector.33</title>
                        <desc>Pointer</desc>
                        <desc>Strong handle</desc>
                        <v:textBlock v:margins="rect(4,4,4,4)"/>
                        <v:textRect cx="-25.4064" cy="533.679" width="55.22" height="17.6036"/>
-                       <path d="M0 544.11 L-98.99 502.36 A3 3 -180 0 0 -104.51 500.03 L-150.69 480.55" class="st13"/>
+                       <path d="M0 544.11 L-98.99 502.36 A3 3 -180 0 0 -104.51 500.03 L-150.69 480.55" class="st12"/>
                        <rect v:rectContext="textBkgnd" x="-48.1052" y="528.879" width="45.398" height="9.59985" class="st9"/>
                        <text x="-48.11" y="536.08" class="st10" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Strong handle</text>                </g>
                <g id="shape35-168" v:mID="35" v:groupContext="shape" transform="translate(431.676,-43.0313)">
                        <desc>...</desc>
                        <v:textBlock v:margins="rect(4,4,4,4)"/>
                        <v:textRect cx="12.375" cy="532.771" width="24.75" height="22.6875"/>
-                       <rect x="0" y="521.427" width="24.75" height="22.6875" class="st15"/>
-                       <text x="7.83" y="536.37" class="st16" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>...</text>            </g>
+                       <rect x="0" y="521.427" width="24.75" height="22.6875" class="st14"/>
+                       <text x="7.83" y="536.37" class="st15" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>...</text>            </g>
                <g id="shape36-171" v:mID="36" v:groupContext="shape" v:layerMember="0" transform="translate(25.6723,-193.449)">
                        <title>Dynamic connector.36</title>
                        <path d="M0 535.54 L91.38 535.4 A3 3 0 1 1 97.38 535.39 L192.3 535.24 A3 3 0 1 1 198.3 535.23 L240.14 535.16 A3 3 0 0
-                                                1 246.14 535.15 L451.38 534.83 A3 3 0 1 1 457.38 534.82 L539.88 534.69" class="st17"/>
+                                                1 246.14 535.15 L391.33 534.92 A3 3 0 1 1 397.33 534.91 L466.33 534.8 A3 3 0 0 1 472.33 534.8 L539.88 534.69"
+                                       class="st16"/>
                </g>
                <g id="shape37-174" v:mID="37" v:groupContext="shape" transform="translate(25.6723,-207.375)">
                        <title>Sheet.37</title>
                        <desc>Managed side</desc>
                        <v:textBlock v:margins="rect(4,4,4,4)"/>
                        <v:textRect cx="44.1562" cy="537.083" width="88.32" height="14.0625"/>
-                       <rect x="0" y="530.052" width="88.3125" height="14.0625" class="st15"/>
-                       <text x="9.95" y="540.68" class="st18" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Managed side</text>           </g>
+                       <rect x="0" y="530.052" width="88.3125" height="14.0625" class="st14"/>
+                       <text x="9.95" y="540.68" class="st17" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Managed side</text>           </g>
                <g id="shape38-177" v:mID="38" v:groupContext="shape" transform="translate(18.375,-180.375)">
                        <title>Sheet.38</title>
                        <desc>Native side</desc>
                        <v:textBlock v:margins="rect(4,4,4,4)"/>
                        <v:textRect cx="44.1562" cy="537.083" width="88.32" height="14.0625"/>
-                       <rect x="0" y="530.052" width="88.3125" height="14.0625" class="st15"/>
-                       <text x="17.11" y="540.68" class="st19" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Native side</text>           </g>
+                       <rect x="0" y="530.052" width="88.3125" height="14.0625" class="st14"/>
+                       <text x="17.11" y="540.68" class="st18" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Native side</text>           </g>
+               <g id="shape39-180" v:mID="39" v:groupContext="shape" v:layerMember="0" transform="translate(486,-171.375)">
+                       <title>Dynamic connector.39</title>
+                       <desc>Strong handle (only during unload)</desc>
+                       <v:textBlock v:margins="rect(4,4,4,4)"/>
+                       <v:textRect cx="9" cy="528.739" width="75.66" height="27.2035"/>
+                       <path d="M9 544.11 L9 484.38" class="st11"/>
+                       <rect v:rectContext="textBkgnd" x="-23.9215" y="519.14" width="65.8433" height="19.1997" class="st9"/>
+                       <text x="-13.7" y="526.34" class="st10" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Strong handle<v:newlineChar/><tspan
+                                               x="-23.92" dy="1.2em" class="st3">(only during unload)</tspan></text>           </g>
        </g>
 </svg>