summaryrefslogtreecommitdiff
path: root/src/binder
diff options
context:
space:
mode:
authorJan Vorlicek <janvorli@microsoft.com>2018-08-23 02:42:43 +0200
committerGitHub <noreply@github.com>2018-08-23 02:42:43 +0200
commit8cd4b39a42c1c7cf37502357e6a4cb2888f5dfd7 (patch)
treea767facb00becfc9b6b9f0c3a8d731e566e3d1c3 /src/binder
parent8013a4b6786d9e6618f8ed36bd0a473aa17b72aa (diff)
downloadcoreclr-8cd4b39a42c1c7cf37502357e6a4cb2888f5dfd7.tar.gz
coreclr-8cd4b39a42c1c7cf37502357e6a4cb2888f5dfd7.tar.bz2
coreclr-8cd4b39a42c1c7cf37502357e6a4cb2888f5dfd7.zip
Enable unloading of AssemblyLoadContext (#18476)
Enable assembly unloading * Allow PInvoke methods on collectible assemblies * Fix test unloadability Several hundreds of tests were using Helper class that created GCHandle, but never freed it. That prevented unloading of those tests. The change modifies the Helper class to keep the handle in a finalizable object. Several GCHandle related tests were not freeing the GCHandle they allocated, so this change adds freeing them to enable the unloading. * Add missing error messages to the resources * Fix shuffle thunk cache for unloadability * Add GetLoaderAllocator to ICLRPrivBinder
Diffstat (limited to 'src/binder')
-rw-r--r--src/binder/assembly.cpp5
-rw-r--r--src/binder/clrprivbinderassemblyloadcontext.cpp74
-rw-r--r--src/binder/clrprivbindercoreclr.cpp6
-rw-r--r--src/binder/inc/assembly.hpp12
-rw-r--r--src/binder/inc/clrprivbinderassemblyloadcontext.h28
-rw-r--r--src/binder/inc/clrprivbindercoreclr.h3
6 files changed, 118 insertions, 10 deletions
diff --git a/src/binder/assembly.cpp b/src/binder/assembly.cpp
index 5d3a674a55..8faa00a908 100644
--- a/src/binder/assembly.cpp
+++ b/src/binder/assembly.cpp
@@ -326,6 +326,11 @@ Exit:
return (m_pBinder == NULL) ? E_FAIL : m_pBinder->GetBinderFlags(pBinderFlags);
}
+ HRESULT Assembly::GetLoaderAllocator(LPVOID* pLoaderAllocator)
+ {
+ return (m_pBinder == NULL) ? E_FAIL : m_pBinder->GetLoaderAllocator(pLoaderAllocator);
+ }
+
HRESULT Assembly::IsShareable(
BOOL * pbIsShareable)
{
diff --git a/src/binder/clrprivbinderassemblyloadcontext.cpp b/src/binder/clrprivbinderassemblyloadcontext.cpp
index e6f957aabe..e1ecdc8436 100644
--- a/src/binder/clrprivbinderassemblyloadcontext.cpp
+++ b/src/binder/clrprivbinderassemblyloadcontext.cpp
@@ -203,6 +203,18 @@ HRESULT CLRPrivBinderAssemblyLoadContext::FindAssemblyBySpec(
return E_FAIL;
}
+HRESULT CLRPrivBinderAssemblyLoadContext::GetLoaderAllocator(LPVOID* pLoaderAllocator)
+{
+ _ASSERTE(pLoaderAllocator != NULL);
+ if (m_pAssemblyLoaderAllocator == NULL)
+ {
+ return E_FAIL;
+ }
+
+ *pLoaderAllocator = m_pAssemblyLoaderAllocator;
+ return S_OK;
+}
+
//=============================================================================
// Creates an instance of the AssemblyLoadContext Binder
//
@@ -212,7 +224,9 @@ HRESULT CLRPrivBinderAssemblyLoadContext::FindAssemblyBySpec(
/* static */
HRESULT CLRPrivBinderAssemblyLoadContext::SetupContext(DWORD dwAppDomainId,
CLRPrivBinderCoreCLR *pTPABinder,
- UINT_PTR ptrAssemblyLoadContext,
+ LoaderAllocator* pLoaderAllocator,
+ void* loaderAllocatorHandle,
+ UINT_PTR ptrAssemblyLoadContext,
CLRPrivBinderAssemblyLoadContext **ppBindContext)
{
HRESULT hr = E_FAIL;
@@ -240,6 +254,20 @@ HRESULT CLRPrivBinderAssemblyLoadContext::SetupContext(DWORD dwAppDomainId,
// AssemblyLoadContext instance
pBinder->m_ptrManagedAssemblyLoadContext = ptrAssemblyLoadContext;
+ if (pLoaderAllocator != NULL)
+ {
+ // Link to LoaderAllocator, keep a reference to it
+ VERIFY(pLoaderAllocator->AddReferenceIfAlive());
+ }
+ pBinder->m_pAssemblyLoaderAllocator = pLoaderAllocator;
+ pBinder->m_loaderAllocatorHandle = loaderAllocatorHandle;
+
+#if !defined(DACCESS_COMPILE) && !defined(CROSSGEN_COMPILE)
+ if (pLoaderAllocator != NULL)
+ {
+ ((AssemblyLoaderAllocator*)pLoaderAllocator)->RegisterBinder(pBinder);
+ }
+#endif
// Return reference to the allocated Binder instance
*ppBindContext = clr::SafeAddRef(pBinder.Extract());
}
@@ -251,9 +279,53 @@ Exit:
return hr;
}
+void CLRPrivBinderAssemblyLoadContext::PrepareForLoadContextRelease(INT_PTR ptrManagedStrongAssemblyLoadContext)
+{
+ CONTRACTL
+ {
+ GC_NOTRIGGER;
+ THROWS;
+ MODE_COOPERATIVE;
+ SO_TOLERANT;
+ }
+ CONTRACTL_END;
+
+ // Replace the weak handle with a strong handle so that the managed assembly load context stays alive until the
+ // CLRPrivBinderAssemblyLoadContext::ReleaseLoadContext is called.
+ OBJECTHANDLE handle = reinterpret_cast<OBJECTHANDLE>(m_ptrManagedAssemblyLoadContext);
+ OBJECTHANDLE strongHandle = reinterpret_cast<OBJECTHANDLE>(ptrManagedStrongAssemblyLoadContext);
+ DestroyShortWeakHandle(handle);
+ m_ptrManagedAssemblyLoadContext = reinterpret_cast<INT_PTR>(strongHandle);
+
+ _ASSERTE(m_pAssemblyLoaderAllocator != NULL);
+ _ASSERTE(m_loaderAllocatorHandle != NULL);
+
+ // We cannot delete the binder here as it is used indirectly when comparing assemblies with the same binder
+ // It will be deleted when the LoaderAllocator will be deleted
+ // But we can release the LoaderAllocator as we are no longer using it here
+ m_pAssemblyLoaderAllocator->Release();
+ m_pAssemblyLoaderAllocator = NULL;
+
+ // Destroy the strong handle to the LoaderAllocator in order to let it reach its finalizer
+ DestroyHandle(reinterpret_cast<OBJECTHANDLE>(m_loaderAllocatorHandle));
+ m_loaderAllocatorHandle = NULL;
+}
+
CLRPrivBinderAssemblyLoadContext::CLRPrivBinderAssemblyLoadContext()
{
m_pTPABinder = NULL;
}
+void CLRPrivBinderAssemblyLoadContext::ReleaseLoadContext()
+{
+ VERIFY(m_ptrManagedAssemblyLoadContext != NULL);
+
+ // This method is called to release the strong handle on the managed AssemblyLoadContext
+ // once the Unloading event has been fired
+ OBJECTHANDLE handle = reinterpret_cast<OBJECTHANDLE>(m_ptrManagedAssemblyLoadContext);
+ DestroyHandle(handle);
+ m_ptrManagedAssemblyLoadContext = NULL;
+}
+
#endif // !defined(DACCESS_COMPILE) && !defined(CROSSGEN_COMPILE)
+
diff --git a/src/binder/clrprivbindercoreclr.cpp b/src/binder/clrprivbindercoreclr.cpp
index d756454edb..051389cb6f 100644
--- a/src/binder/clrprivbindercoreclr.cpp
+++ b/src/binder/clrprivbindercoreclr.cpp
@@ -292,6 +292,12 @@ Exit:
return hr;
}
+HRESULT CLRPrivBinderCoreCLR::GetLoaderAllocator(LPVOID* pLoaderAllocator)
+{
+ // Not supported by this binder
+ return E_FAIL;
+}
+
#ifndef CROSSGEN_COMPILE
HRESULT CLRPrivBinderCoreCLR::PreBindByteArray(PEImage *pPEImage, BOOL fInspectionOnly)
{
diff --git a/src/binder/inc/assembly.hpp b/src/binder/inc/assembly.hpp
index 425e80567e..7071e2eaa0 100644
--- a/src/binder/inc/assembly.hpp
+++ b/src/binder/inc/assembly.hpp
@@ -100,6 +100,8 @@ namespace BINDER_SPACE
STDMETHOD(GetBinderFlags)(DWORD *pBinderFlags);
+ STDMETHOD(GetLoaderAllocator)(LPVOID* pLoaderAllocator);
+
// --------------------------------------------------------------------
// Assembly methods
// --------------------------------------------------------------------
@@ -137,6 +139,11 @@ namespace BINDER_SPACE
static PEKIND GetSystemArchitecture();
static BOOL IsValidArchitecture(PEKIND kArchitecture);
+ inline ICLRPrivBinder* GetBinder()
+ {
+ return m_pBinder;
+ }
+
#ifndef CROSSGEN_COMPILE
protected:
#endif
@@ -195,11 +202,6 @@ public:
_ASSERTE(m_pBinder == NULL || m_pBinder == pBinder);
m_pBinder = pBinder;
}
-
- inline ICLRPrivBinder* GetBinder()
- {
- return m_pBinder;
- }
friend class ::CLRPrivBinderCoreCLR;
diff --git a/src/binder/inc/clrprivbinderassemblyloadcontext.h b/src/binder/inc/clrprivbinderassemblyloadcontext.h
index 9c772338d6..9f3159f694 100644
--- a/src/binder/inc/clrprivbinderassemblyloadcontext.h
+++ b/src/binder/inc/clrprivbinderassemblyloadcontext.h
@@ -17,7 +17,14 @@ namespace BINDER_SPACE
class AssemblyIdentityUTF8;
};
-class CLRPrivBinderAssemblyLoadContext : public IUnknownCommon<ICLRPrivBinder>
+class AppDomain;
+
+class Object;
+class Assembly;
+class LoaderAllocator;
+
+class CLRPrivBinderAssemblyLoadContext :
+ public IUnknownCommon<ICLRPrivBinder>
{
public:
@@ -45,14 +52,24 @@ public:
/* [out] */ HRESULT *pResult,
/* [out] */ ICLRPrivAssembly **ppAssembly);
+ STDMETHOD(GetLoaderAllocator)(
+ /* [retval][out] */ LPVOID *pLoaderAllocator);
+
public:
//=========================================================================
// Class functions
//-------------------------------------------------------------------------
- static HRESULT SetupContext(DWORD dwAppDomainId, CLRPrivBinderCoreCLR *pTPABinder,
- UINT_PTR ptrAssemblyLoadContext, CLRPrivBinderAssemblyLoadContext **ppBindContext);
-
+ static HRESULT SetupContext(DWORD dwAppDomainId,
+ CLRPrivBinderCoreCLR *pTPABinder,
+ LoaderAllocator* pLoaderAllocator,
+ void* loaderAllocatorHandle,
+ UINT_PTR ptrAssemblyLoadContext,
+ CLRPrivBinderAssemblyLoadContext **ppBindContext);
+
+ void PrepareForLoadContextRelease(INT_PTR ptrManagedStrongAssemblyLoadContext);
+ void ReleaseLoadContext();
+
CLRPrivBinderAssemblyLoadContext();
inline BINDER_SPACE::ApplicationContext *GetAppContext()
@@ -80,6 +97,9 @@ private:
CLRPrivBinderCoreCLR *m_pTPABinder;
INT_PTR m_ptrManagedAssemblyLoadContext;
+
+ LoaderAllocator* m_pAssemblyLoaderAllocator;
+ void* m_loaderAllocatorHandle;
};
#endif // !defined(DACCESS_COMPILE) && !defined(CROSSGEN_COMPILE)
diff --git a/src/binder/inc/clrprivbindercoreclr.h b/src/binder/inc/clrprivbindercoreclr.h
index 9338fad3df..e0e82866b6 100644
--- a/src/binder/inc/clrprivbindercoreclr.h
+++ b/src/binder/inc/clrprivbindercoreclr.h
@@ -42,6 +42,9 @@ public:
/* [out] */ HRESULT *pResult,
/* [out] */ ICLRPrivAssembly **ppAssembly);
+ STDMETHOD(GetLoaderAllocator)(
+ /* [retval][out] */ LPVOID *pLoaderAllocator);
+
public:
HRESULT SetupBindingPaths(SString &sTrustedPlatformAssemblies,