Aquire exclusive lock when creating application info (#1142)
This commit is contained in:
parent
1d1b2155c4
commit
477fd1d90d
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp2.2</TargetFramework>
|
||||
<InProcessTestSite>true</InProcessTestSite>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -44,24 +44,40 @@ APPLICATION_MANAGER::GetOrCreateApplicationInfo(
|
|||
// key in the applicationInfoHash.
|
||||
pszApplicationId = pApplication.GetApplicationId();
|
||||
|
||||
// When accessing the m_pApplicationInfoHash, we need to acquire the application manager
|
||||
// lock to avoid races on setting state.
|
||||
SRWSharedLock lock(m_srwLock);
|
||||
if (!m_fDebugInitialize)
|
||||
{
|
||||
DebugInitializeFromConfig(m_pHttpServer, pApplication);
|
||||
m_fDebugInitialize = TRUE;
|
||||
}
|
||||
// When accessing the m_pApplicationInfoHash, we need to acquire the application manager
|
||||
// lock to avoid races on setting state.
|
||||
SRWSharedLock readLock(m_srwLock);
|
||||
if (!m_fDebugInitialize)
|
||||
{
|
||||
DebugInitializeFromConfig(m_pHttpServer, pApplication);
|
||||
m_fDebugInitialize = TRUE;
|
||||
}
|
||||
|
||||
if (g_fInShutdown)
|
||||
{
|
||||
FINISHED(HRESULT_FROM_WIN32(ERROR_SERVER_SHUTDOWN_IN_PROGRESS));
|
||||
}
|
||||
if (g_fInShutdown)
|
||||
{
|
||||
FINISHED(HRESULT_FROM_WIN32(ERROR_SERVER_SHUTDOWN_IN_PROGRESS));
|
||||
}
|
||||
|
||||
m_pApplicationInfoHash->FindKey(pszApplicationId, ppApplicationInfo);
|
||||
m_pApplicationInfoHash->FindKey(pszApplicationId, ppApplicationInfo);
|
||||
|
||||
// It's important to release read lock here so exclusive lock
|
||||
// can be reacquired later as SRW lock doesn't allow upgrades
|
||||
}
|
||||
|
||||
if (*ppApplicationInfo == NULL)
|
||||
{
|
||||
// Take exclusive lock before creating the application
|
||||
SRWExclusiveLock writeLock(m_srwLock);
|
||||
|
||||
// Check if other thread created the application
|
||||
|
||||
m_pApplicationInfoHash->FindKey(pszApplicationId, ppApplicationInfo);
|
||||
if (*ppApplicationInfo != NULL)
|
||||
{
|
||||
FINISHED(S_OK);
|
||||
}
|
||||
|
||||
pApplicationInfo = new APPLICATION_INFO(m_pHttpServer);
|
||||
|
||||
FINISHED_IF_FAILED(pApplicationInfo->Initialize(pApplication));
|
||||
|
|
@ -187,7 +203,7 @@ APPLICATION_MANAGER::RecycleApplicationFromManager(
|
|||
DWORD dwPreviousCounter = 0;
|
||||
APPLICATION_INFO_HASH* table = NULL;
|
||||
CONFIG_CHANGE_CONTEXT context;
|
||||
|
||||
|
||||
if (g_fInShutdown)
|
||||
{
|
||||
// We are already shutting down, ignore this event as a global configuration change event
|
||||
|
|
|
|||
|
|
@ -0,0 +1,48 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Server.IIS.FunctionalTests.Utilities;
|
||||
using Microsoft.AspNetCore.Server.IntegrationTesting;
|
||||
using Microsoft.AspNetCore.Server.IntegrationTesting.IIS;
|
||||
using Microsoft.AspNetCore.Testing.xunit;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
|
||||
{
|
||||
[Collection(PublishedSitesCollection.Name)]
|
||||
public class CommonStartupTests : IISFunctionalTestBase
|
||||
{
|
||||
private readonly PublishedSitesFixture _fixture;
|
||||
|
||||
public CommonStartupTests(PublishedSitesFixture fixture)
|
||||
{
|
||||
_fixture = fixture;
|
||||
}
|
||||
|
||||
public static TestMatrix TestVariants
|
||||
=> TestMatrix.ForServers(DeployerSelector.ServerType)
|
||||
.WithTfms(Tfm.NetCoreApp22)
|
||||
.WithAllApplicationTypes()
|
||||
.WithAllAncmVersions()
|
||||
.WithAllHostingModels();
|
||||
|
||||
[ConditionalTheory]
|
||||
[MemberData(nameof(TestVariants))]
|
||||
public async Task StartupStress(TestVariant variant)
|
||||
{
|
||||
var deploymentParameters = _fixture.GetBaseDeploymentParameters(variant, publish: true);
|
||||
|
||||
var deploymentResult = await DeployAsync(deploymentParameters);
|
||||
|
||||
await Helpers.StressLoad(deploymentResult.HttpClient, "/HelloWorld", response => {
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
Assert.Equal("Hello World", response.Content.ReadAsStringAsync().GetAwaiter().GetResult());
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue