Merge branch 'merge/release/2.2-to-master'
This commit is contained in:
commit
dc1445cc62
|
|
@ -3,6 +3,8 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <random>
|
||||||
|
|
||||||
#define MIN_PORT 1025
|
#define MIN_PORT 1025
|
||||||
#define MAX_PORT 48000
|
#define MAX_PORT 48000
|
||||||
#define MAX_RETRY 10
|
#define MAX_RETRY 10
|
||||||
|
|
@ -303,6 +305,8 @@ private:
|
||||||
volatile BOOL m_fReady;
|
volatile BOOL m_fReady;
|
||||||
mutable LONG m_cRefs;
|
mutable LONG m_cRefs;
|
||||||
|
|
||||||
|
std::mt19937 m_randomGenerator;
|
||||||
|
|
||||||
DWORD m_dwPort;
|
DWORD m_dwPort;
|
||||||
DWORD m_dwStartupTimeLimitInMS;
|
DWORD m_dwStartupTimeLimitInMS;
|
||||||
DWORD m_dwShutdownTimeLimitInMS;
|
DWORD m_dwShutdownTimeLimitInMS;
|
||||||
|
|
@ -331,4 +335,4 @@ private:
|
||||||
|
|
||||||
PROCESS_MANAGER *m_pProcessManager;
|
PROCESS_MANAGER *m_pProcessManager;
|
||||||
ENVIRONMENT_VAR_HASH *m_pEnvironmentVarTable ;
|
ENVIRONMENT_VAR_HASH *m_pEnvironmentVarTable ;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -89,13 +89,15 @@ SERVER_PROCESS::GetRandomPort
|
||||||
BOOL fPortInUse = FALSE;
|
BOOL fPortInUse = FALSE;
|
||||||
DWORD dwActualProcessId = 0;
|
DWORD dwActualProcessId = 0;
|
||||||
|
|
||||||
|
std::uniform_int_distribution<> dist(MIN_PORT, MAX_PORT);
|
||||||
|
|
||||||
if (g_fNsiApiNotSupported)
|
if (g_fNsiApiNotSupported)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
// the default value for optional parameter dwExcludedPort is 0 which is reserved
|
// the default value for optional parameter dwExcludedPort is 0 which is reserved
|
||||||
// a random number between MIN_PORT and MAX_PORT
|
// a random number between MIN_PORT and MAX_PORT
|
||||||
//
|
//
|
||||||
while ((*pdwPickedPort = (rand() % (MAX_PORT - MIN_PORT)) + MIN_PORT + 1) == dwExcludedPort);
|
while ((*pdwPickedPort = dist(m_randomGenerator)) == dwExcludedPort);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -107,7 +109,7 @@ SERVER_PROCESS::GetRandomPort
|
||||||
// determing whether the randomly generated port is
|
// determing whether the randomly generated port is
|
||||||
// in use by any other process.
|
// in use by any other process.
|
||||||
//
|
//
|
||||||
while ((*pdwPickedPort = (rand() % (MAX_PORT - MIN_PORT)) + MIN_PORT + 1) == dwExcludedPort);
|
while ((*pdwPickedPort = dist(m_randomGenerator)) == dwExcludedPort);
|
||||||
hr = CheckIfServerIsUp(*pdwPickedPort, &dwActualProcessId, &fPortInUse);
|
hr = CheckIfServerIsUp(*pdwPickedPort, &dwActualProcessId, &fPortInUse);
|
||||||
} while (fPortInUse && ++cRetry < MAX_RETRY);
|
} while (fPortInUse && ++cRetry < MAX_RETRY);
|
||||||
|
|
||||||
|
|
@ -1909,10 +1911,10 @@ SERVER_PROCESS::SERVER_PROCESS() :
|
||||||
m_pForwarderConnection( NULL ),
|
m_pForwarderConnection( NULL ),
|
||||||
m_dwListeningProcessId( 0 ),
|
m_dwListeningProcessId( 0 ),
|
||||||
m_hListeningProcessHandle( NULL ),
|
m_hListeningProcessHandle( NULL ),
|
||||||
m_hShutdownHandle( NULL )
|
m_hShutdownHandle( NULL ),
|
||||||
|
m_randomGenerator( std::random_device()() )
|
||||||
{
|
{
|
||||||
InterlockedIncrement(&g_dwActiveServerProcesses);
|
InterlockedIncrement(&g_dwActiveServerProcesses);
|
||||||
srand(GetTickCount());
|
|
||||||
|
|
||||||
for(INT i=0;i<MAX_ACTIVE_CHILD_PROCESSES; ++i)
|
for(INT i=0;i<MAX_ACTIVE_CHILD_PROCESSES; ++i)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -48,11 +48,6 @@ APPLICATION_MANAGER::GetOrCreateApplicationInfo(
|
||||||
// When accessing the m_pApplicationInfoHash, we need to acquire the application manager
|
// When accessing the m_pApplicationInfoHash, we need to acquire the application manager
|
||||||
// lock to avoid races on setting state.
|
// lock to avoid races on setting state.
|
||||||
SRWSharedLock readLock(m_srwLock);
|
SRWSharedLock readLock(m_srwLock);
|
||||||
if (!m_fDebugInitialize)
|
|
||||||
{
|
|
||||||
DebugInitializeFromConfig(m_pHttpServer, pApplication);
|
|
||||||
m_fDebugInitialize = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (g_fInShutdown)
|
if (g_fInShutdown)
|
||||||
{
|
{
|
||||||
|
|
@ -70,8 +65,13 @@ APPLICATION_MANAGER::GetOrCreateApplicationInfo(
|
||||||
// Take exclusive lock before creating the application
|
// Take exclusive lock before creating the application
|
||||||
SRWExclusiveLock writeLock(m_srwLock);
|
SRWExclusiveLock writeLock(m_srwLock);
|
||||||
|
|
||||||
// Check if other thread created the application
|
if (!m_fDebugInitialize)
|
||||||
|
{
|
||||||
|
DebugInitializeFromConfig(m_pHttpServer, pApplication);
|
||||||
|
m_fDebugInitialize = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if other thread created the application
|
||||||
m_pApplicationInfoHash->FindKey(pszApplicationId, ppApplicationInfo);
|
m_pApplicationInfoHash->FindKey(pszApplicationId, ppApplicationInfo);
|
||||||
if (*ppApplicationInfo != NULL)
|
if (*ppApplicationInfo != NULL)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -107,13 +107,15 @@ SERVER_PROCESS::GetRandomPort
|
||||||
BOOL fPortInUse = FALSE;
|
BOOL fPortInUse = FALSE;
|
||||||
DWORD dwActualProcessId = 0;
|
DWORD dwActualProcessId = 0;
|
||||||
|
|
||||||
|
std::uniform_int_distribution<> dist(MIN_PORT, MAX_PORT);
|
||||||
|
|
||||||
if (g_fNsiApiNotSupported)
|
if (g_fNsiApiNotSupported)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
// the default value for optional parameter dwExcludedPort is 0 which is reserved
|
// the default value for optional parameter dwExcludedPort is 0 which is reserved
|
||||||
// a random number between MIN_PORT and MAX_PORT
|
// a random number between MIN_PORT and MAX_PORT
|
||||||
//
|
//
|
||||||
while ((*pdwPickedPort = (rand() % (MAX_PORT - MIN_PORT)) + MIN_PORT + 1) == dwExcludedPort);
|
while ((*pdwPickedPort = dist(m_randomGenerator)) == dwExcludedPort);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -125,7 +127,7 @@ SERVER_PROCESS::GetRandomPort
|
||||||
// determing whether the randomly generated port is
|
// determing whether the randomly generated port is
|
||||||
// in use by any other process.
|
// in use by any other process.
|
||||||
//
|
//
|
||||||
while ((*pdwPickedPort = (rand() % (MAX_PORT - MIN_PORT)) + MIN_PORT + 1) == dwExcludedPort);
|
while ((*pdwPickedPort = dist(m_randomGenerator)) == dwExcludedPort);
|
||||||
hr = CheckIfServerIsUp(*pdwPickedPort, &dwActualProcessId, &fPortInUse);
|
hr = CheckIfServerIsUp(*pdwPickedPort, &dwActualProcessId, &fPortInUse);
|
||||||
} while (fPortInUse && ++cRetry < MAX_RETRY);
|
} while (fPortInUse && ++cRetry < MAX_RETRY);
|
||||||
|
|
||||||
|
|
@ -1705,10 +1707,10 @@ SERVER_PROCESS::SERVER_PROCESS() :
|
||||||
m_pForwarderConnection(NULL),
|
m_pForwarderConnection(NULL),
|
||||||
m_dwListeningProcessId(0),
|
m_dwListeningProcessId(0),
|
||||||
m_hListeningProcessHandle(NULL),
|
m_hListeningProcessHandle(NULL),
|
||||||
m_hShutdownHandle(NULL)
|
m_hShutdownHandle(NULL),
|
||||||
|
m_randomGenerator(std::random_device()())
|
||||||
{
|
{
|
||||||
//InterlockedIncrement(&g_dwActiveServerProcesses);
|
//InterlockedIncrement(&g_dwActiveServerProcesses);
|
||||||
srand(GetTickCount());
|
|
||||||
|
|
||||||
for (INT i=0; i<MAX_ACTIVE_CHILD_PROCESSES; ++i)
|
for (INT i=0; i<MAX_ACTIVE_CHILD_PROCESSES; ++i)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,8 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <random>
|
||||||
|
|
||||||
#define MIN_PORT 1025
|
#define MIN_PORT 1025
|
||||||
#define MAX_PORT 48000
|
#define MAX_PORT 48000
|
||||||
#define MAX_RETRY 10
|
#define MAX_RETRY 10
|
||||||
|
|
@ -257,6 +259,8 @@ private:
|
||||||
volatile BOOL m_fReady;
|
volatile BOOL m_fReady;
|
||||||
mutable LONG m_cRefs;
|
mutable LONG m_cRefs;
|
||||||
|
|
||||||
|
std::mt19937 m_randomGenerator;
|
||||||
|
|
||||||
DWORD m_dwPort;
|
DWORD m_dwPort;
|
||||||
DWORD m_dwStartupTimeLimitInMS;
|
DWORD m_dwStartupTimeLimitInMS;
|
||||||
DWORD m_dwShutdownTimeLimitInMS;
|
DWORD m_dwShutdownTimeLimitInMS;
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting
|
||||||
|
|
||||||
protected ApplicationDeployer _deployer;
|
protected ApplicationDeployer _deployer;
|
||||||
|
|
||||||
protected virtual async Task<IISDeploymentResult> DeployAsync(IISDeploymentParameters parameters)
|
protected ApplicationDeployer CreateDeployer(IISDeploymentParameters parameters)
|
||||||
{
|
{
|
||||||
if (!parameters.EnvironmentVariables.ContainsKey(DebugEnvironmentVariable))
|
if (!parameters.EnvironmentVariables.ContainsKey(DebugEnvironmentVariable))
|
||||||
{
|
{
|
||||||
|
|
@ -37,8 +37,12 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting
|
||||||
throw new InvalidOperationException("All tests should use ApplicationPublisher");
|
throw new InvalidOperationException("All tests should use ApplicationPublisher");
|
||||||
}
|
}
|
||||||
|
|
||||||
_deployer = IISApplicationDeployerFactory.Create(parameters, LoggerFactory);
|
return IISApplicationDeployerFactory.Create(parameters, LoggerFactory);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual async Task<IISDeploymentResult> DeployAsync(IISDeploymentParameters parameters)
|
||||||
|
{
|
||||||
|
_deployer = CreateDeployer(parameters);
|
||||||
return (IISDeploymentResult)await _deployer.DeployAsync();
|
return (IISDeploymentResult)await _deployer.DeployAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
// 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.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Server.IntegrationTesting
|
||||||
|
{
|
||||||
|
public class DisposableList<T> : List<T>, IDisposable where T : IDisposable
|
||||||
|
{
|
||||||
|
public DisposableList() : base() { }
|
||||||
|
|
||||||
|
public DisposableList(IEnumerable<T> collection) : base(collection) { }
|
||||||
|
|
||||||
|
public DisposableList(int capacity) : base(capacity) { }
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
foreach (var item in this)
|
||||||
|
{
|
||||||
|
item?.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
// 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.Collections.Generic;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Server.IIS.FunctionalTests.Utilities;
|
||||||
|
using Microsoft.AspNetCore.Server.IntegrationTesting;
|
||||||
|
using Microsoft.AspNetCore.Testing.xunit;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
|
||||||
|
{
|
||||||
|
[Collection(PublishedSitesCollection.Name)]
|
||||||
|
public class MultipleAppTests : IISFunctionalTestBase
|
||||||
|
{
|
||||||
|
private readonly PublishedSitesFixture _fixture;
|
||||||
|
|
||||||
|
public MultipleAppTests(PublishedSitesFixture fixture)
|
||||||
|
{
|
||||||
|
_fixture = fixture;
|
||||||
|
}
|
||||||
|
|
||||||
|
[ConditionalTheory]
|
||||||
|
[InlineData(AncmVersion.AspNetCoreModule)]
|
||||||
|
[InlineData(AncmVersion.AspNetCoreModuleV2)]
|
||||||
|
public async Task Startup(AncmVersion ancmVersion)
|
||||||
|
{
|
||||||
|
const int numApps = 10;
|
||||||
|
|
||||||
|
using (var deployers = new DisposableList<ApplicationDeployer>())
|
||||||
|
{
|
||||||
|
var deploymentResults = new List<DeploymentResult>();
|
||||||
|
|
||||||
|
// Deploy all apps
|
||||||
|
for (var i = 0; i < numApps; i++)
|
||||||
|
{
|
||||||
|
var deploymentParameters = _fixture.GetBaseDeploymentParameters(hostingModel: IntegrationTesting.HostingModel.OutOfProcess);
|
||||||
|
deploymentParameters.AncmVersion = ancmVersion;
|
||||||
|
|
||||||
|
var deployer = CreateDeployer(deploymentParameters);
|
||||||
|
deployers.Add(deployer);
|
||||||
|
deploymentResults.Add(await deployer.DeployAsync());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start all requests as quickly as possible, so apps are started as quickly as possible,
|
||||||
|
// to test possible race conditions when multiple apps start at the same time.
|
||||||
|
var requestTasks = new List<Task<HttpResponseMessage>>();
|
||||||
|
foreach (var deploymentResult in deploymentResults)
|
||||||
|
{
|
||||||
|
requestTasks.Add(deploymentResult.HttpClient.GetAsync("/HelloWorld"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify all apps started and return expected response
|
||||||
|
foreach (var requestTask in requestTasks)
|
||||||
|
{
|
||||||
|
var response = await requestTask;
|
||||||
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||||
|
var responseText = await response.Content.ReadAsStringAsync();
|
||||||
|
Assert.Equal("Hello World", responseText);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue