Утечка памяти в SPActiveDirectoryClaimProvider?
-
10-12-2019 - |
Вопрос
играя с поставщиком пользовательских утверждений, я нашел интересную вещь в SPActiveDirectoryClaimProvider
.Если вы исследуете код с помощью любого браузера\декомпилятора сборок .net (.NET Reflector или ILSpy), вы обнаружите утечку памяти размером SPWeb
объект в методе FillResolve
.Посмотрите внимательно на код:
// Microsoft.SharePoint.Administration.Claims.SPActiveDirectoryClaimProvider
private void FillResolve(Uri context, string[] entityTypes, bool inputIsEmailOnly, string resolveInput, List<PickerEntity> resolved)
{
SPWeb sPWeb = null;
SPSite sPSite = null;
if (!SPThreadContext.Items.Contains("SPActiveDirectoryClaimProviderIgnoreContext"))
{
bool catchAccessDeniedException = SPSecurity.CatchAccessDeniedException;
try
{
SPSecurity.CatchAccessDeniedException = false;
sPSite = new SPSite(context.AbsoluteUri);
if (sPSite != null)
{
sPWeb = sPSite.OpenWeb();
}
if (!sPWeb.Exists)
{
sPWeb = null;
}
}
catch
{
if (sPSite != null)
{
sPSite.Dispose();
sPWeb = null;
}
}
finally
{
SPSecurity.CatchAccessDeniedException = catchAccessDeniedException;
}
}
try
{
SPWebApplication webApp = SPWebApplication.Lookup(context);
SPPrincipalType scopes = SPActiveDirectoryClaimProvider.ConvertEntityTypeToPrincipalTypes(entityTypes);
SPPrincipalInfo sPPrincipalInfo = SPUtility.ResolveWindowsPrincipal(sPWeb, webApp, resolveInput, scopes, inputIsEmailOnly);
if (sPPrincipalInfo != null)
{
if (inputIsEmailOnly && MatchType.EmailAddress == sPPrincipalInfo.MatchType && SPActiveDirectoryClaimProvider.DisableEmailResolve())
{
ULS.SendTraceTag(2466693u, ULSCat.msoulscat_WSS_ClaimsAuthentication, ULSTraceLevel.VerboseEx, "Dicarding match '{0}' for input '{1}' because it is email match and feature is disabled.", new object[]
{
sPPrincipalInfo.LoginName,
resolveInput
});
}
else
{
PickerEntity pickerEntity = this.CreatePickerEntity(sPPrincipalInfo);
if (pickerEntity != null)
{
resolved.Add(pickerEntity);
ULS.SendTraceTag(1634481712u, ULSCat.msoulscat_WSS_ClaimsAuthentication, ULSTraceLevel.VerboseEx, string.Format(CultureInfo.InvariantCulture, "Returning AD resolve match '{0}' for input '{1}'.", new object[]
{
pickerEntity.Key,
resolveInput
}));
}
}
}
else
{
if (!inputIsEmailOnly)
{
int maxCount = 10;
bool flag = false;
IList<SPPrincipalInfo> list;
if (sPWeb != null)
{
list = SPUtility.SearchPrincipals(sPWeb, resolveInput, scopes, SPPrincipalSource.Windows, null, maxCount, out flag);
}
else
{
list = SPUtility.SearchWindowsPrincipals(webApp, resolveInput, scopes, maxCount, out flag);
}
List<PickerEntity> list2 = new List<PickerEntity>();
foreach (SPPrincipalInfo current in list)
{
if (inputIsEmailOnly && MatchType.EmailAddress == current.MatchType && SPActiveDirectoryClaimProvider.DisableEmailResolve())
{
ULS.SendTraceTag(2466694u, ULSCat.msoulscat_WSS_ClaimsAuthentication, ULSTraceLevel.VerboseEx, "Dicarding match '{0}' for input '{1}' because it is email match and feature is disabled.", new object[]
{
current.LoginName,
resolveInput
});
}
else
{
PickerEntity pickerEntity2 = this.CreatePickerEntity(current);
if (pickerEntity2 != null)
{
list2.Add(pickerEntity2);
ULS.SendTraceTag(1634481713u, ULSCat.msoulscat_WSS_ClaimsAuthentication, ULSTraceLevel.VerboseEx, string.Format(CultureInfo.InvariantCulture, "Returning AD resolve search match '{0}' for input '{1}'.", new object[]
{
pickerEntity2.Key,
resolveInput
}));
}
}
}
if (list2.Count == 1 && list2[0].Claim != null && SPClaim.EqualClaimValues(list2[0].Claim.Value, resolveInput))
{
resolved.Add(list2[0]);
}
else
{
if (list2.Count > 0)
{
PickerEntity pickerEntity = base.CreatePickerEntity();
pickerEntity.IsResolved = false;
pickerEntity.DisplayText = resolveInput;
pickerEntity.MultipleMatches.AddRange(list2);
resolved.Add(pickerEntity);
}
}
}
}
}
catch
{
throw;
}
finally
{
if (sPSite != null)
{
sPSite.Dispose();
}
}
}
Согласно лучшей практике (http://msdn.microsoft.com/en-us/library/office/ee557362%28v=office.14%29.aspx) мы должны избавиться SPWeb
объекты, созданные с помощью OpenWeb
метод.Но sPWeb
объект не удаляется ни в одной части метода.Это означает, что каждый раз, когда мы выполняем поиск и разрешение в средстве выбора людей, один SPWeb
объект будет утерян.У меня нет подписки MSDN, чтобы связаться с Microsoft по поводу этой проблемы.Эта проблема актуальна для SharePoint 2010 (SP2) и SharePoint 2013 (SP1).
Я считаю, что сообщество может подтвердить утечку памяти и связаться с Microsoft, чтобы решить эту проблему.
Решение
Вызов Dispose() на SPSite, на котором использовался метод OpenWeb, автоматически удалит открытый им SPWeb.Пока SPSite удаляется, у вас не возникнет здесь проблем, если только вы не откроете тонну SPWeb и не удалите их явно.
Глядя на этот код, кажется, что он удаляет SPSite, так что все должно быть в порядке.
РЕДАКТИРОВАТЬ
Для справки, вот метод .Close() из класса SPSite, вызываемый методом .Dispose().Как вы можете видеть, перед удалением себя он удалил все открытые SPWeb:
public void Close()
{
SPEventManager.WaitForPostEvents();
if (this.m_openedWebs != null)
{
SPWeakObjectHandleList<SPWeb> list = new SPWeakObjectHandleList<SPWeb>(this.m_openedWebs);
foreach (SPWeb web in list)
{
web.Close();
}
list.Dispose();
this.m_openedWebs.Dispose();
}
this.m_rootWebCreated = false;
SPRequestContext.UnregisterSite(this);
this.InvalidateSite();
}