diff --git a/.vsts-pipelines/templates/build-steps.yml b/.vsts-pipelines/templates/build-steps.yml
index dbc03620b5..2d6544e107 100644
--- a/.vsts-pipelines/templates/build-steps.yml
+++ b/.vsts-pipelines/templates/build-steps.yml
@@ -3,16 +3,26 @@ phases:
parameters:
agentOs: Windows
beforeBuild:
- - powershell: "& ./tools/UpdateIISExpressCertificate.ps1; & ./tools/update_schema.ps1"
+ - powershell: "& ./tools/UpdateIISExpressCertificate.ps1; & ./tools/update_schema.ps1; & ./tools/SetupTestEnvironment.ps1 Setup"
displayName: Prepare repo
afterBuild:
+ - powershell: "& ./tools/SetupTestEnvironment.ps1 Shutdown"
+ displayName: Stop AppVerifier
+ condition: always()
- task: PublishBuildArtifacts@1
- displayName: Upload binlog
+ displayName: Upload logs
condition: eq(variables['system.pullrequest.isfork'], false)
inputs:
artifactName: logs
artifactType: Container
- pathtoPublish: artifacts/logs/
+ pathtoPublish: artifacts/logs
+ - task: PublishBuildArtifacts@1
+ displayName: Upload dumps
+ condition: eq(variables['system.pullrequest.isfork'], false)
+ inputs:
+ artifactName: dumps
+ artifactType: Container
+ pathtoPublish: artifacts/dumps
- template: .vsts-pipelines/templates/phases/default-build.yml@buildtools
parameters:
diff --git a/Directory.Build.props b/Directory.Build.props
index f015ba2785..a328745f31 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -18,6 +18,8 @@
MicrosoftNuGet
true
true
+
+ false
diff --git a/src/AspNetCoreModuleV2/InProcessRequestHandler/dllmain.cpp b/src/AspNetCoreModuleV2/InProcessRequestHandler/dllmain.cpp
index ca40d04e36..2a0369206b 100644
--- a/src/AspNetCoreModuleV2/InProcessRequestHandler/dllmain.cpp
+++ b/src/AspNetCoreModuleV2/InProcessRequestHandler/dllmain.cpp
@@ -75,6 +75,8 @@ BOOL APIENTRY DllMain(HMODULE hModule,
break;
case DLL_PROCESS_DETACH:
g_fProcessDetach = TRUE;
+ IN_PROCESS_HANDLER::StaticTerminate();
+ ALLOC_CACHE_HANDLER::StaticTerminate();
DebugStop();
default:
break;
diff --git a/src/AspNetCoreModuleV2/InProcessRequestHandler/inprocessapplication.cpp b/src/AspNetCoreModuleV2/InProcessRequestHandler/inprocessapplication.cpp
index b9746ff204..352ec7b093 100644
--- a/src/AspNetCoreModuleV2/InProcessRequestHandler/inprocessapplication.cpp
+++ b/src/AspNetCoreModuleV2/InProcessRequestHandler/inprocessapplication.cpp
@@ -259,7 +259,6 @@ IN_PROCESS_APPLICATION::LoadManagedApplication
// Set up stdout redirect
SRWExclusiveLock lock(m_stateLock);
-
if (m_pLoggerProvider == NULL)
{
hr = LoggingHelpers::CreateLoggingProvider(
@@ -394,28 +393,22 @@ IN_PROCESS_APPLICATION::SetEnvironementVariablesOnWorkerProcess(
{
HRESULT hr = S_OK;
ENVIRONMENT_VAR_HASH* pHashTable = NULL;
- if (FAILED(hr = ENVIRONMENT_VAR_HELPERS::InitEnvironmentVariablesTable(
+ std::unique_ptr table;
+ RETURN_IF_FAILED(hr = ENVIRONMENT_VAR_HELPERS::InitEnvironmentVariablesTable(
m_pConfig->QueryEnvironmentVariables(),
m_pConfig->QueryWindowsAuthEnabled(),
m_pConfig->QueryBasicAuthEnabled(),
m_pConfig->QueryAnonymousAuthEnabled(),
- &pHashTable)))
- {
- goto Finished;
- }
+ &pHashTable));
- pHashTable->Apply(ENVIRONMENT_VAR_HELPERS::AppendEnvironmentVariables, &hr);
- if (FAILED(hr))
- {
- goto Finished;
- }
- pHashTable->Apply(ENVIRONMENT_VAR_HELPERS::SetEnvironmentVariables, &hr);
- if (FAILED(hr))
- {
- goto Finished;
- }
-Finished:
- return hr;
+ table.reset(pHashTable);
+
+ table->Apply(ENVIRONMENT_VAR_HELPERS::AppendEnvironmentVariables, &hr);
+ RETURN_IF_FAILED(hr);
+
+ table->Apply(ENVIRONMENT_VAR_HELPERS::SetEnvironmentVariables, &hr);
+ RETURN_IF_FAILED(hr);
+ return S_OK;
}
HRESULT
diff --git a/src/AspNetCoreModuleV2/InProcessRequestHandler/inprocesshandler.cpp b/src/AspNetCoreModuleV2/InProcessRequestHandler/inprocesshandler.cpp
index 90b3bd9d53..0b7357f5d2 100644
--- a/src/AspNetCoreModuleV2/InProcessRequestHandler/inprocesshandler.cpp
+++ b/src/AspNetCoreModuleV2/InProcessRequestHandler/inprocesshandler.cpp
@@ -180,11 +180,18 @@ HRESULT
Finished:
if (FAILED(hr))
{
- if (sm_pAlloc != NULL)
- {
- delete sm_pAlloc;
- sm_pAlloc = NULL;
- }
+ StaticTerminate();
}
return hr;
}
+
+// static
+void
+IN_PROCESS_HANDLER::StaticTerminate(VOID)
+{
+ if (sm_pAlloc != NULL)
+ {
+ delete sm_pAlloc;
+ sm_pAlloc = NULL;
+ }
+}
diff --git a/src/AspNetCoreModuleV2/InProcessRequestHandler/inprocesshandler.h b/src/AspNetCoreModuleV2/InProcessRequestHandler/inprocesshandler.h
index fe0331da9b..ac6aa24789 100644
--- a/src/AspNetCoreModuleV2/InProcessRequestHandler/inprocesshandler.h
+++ b/src/AspNetCoreModuleV2/InProcessRequestHandler/inprocesshandler.h
@@ -70,6 +70,10 @@ public:
HRESULT
StaticInitialize(VOID);
+ static
+ void
+ StaticTerminate(VOID);
+
private:
REQUEST_NOTIFICATION_STATUS
ServerShutdownMessage() const;
diff --git a/src/AspNetCoreModuleV2/OutOfProcessRequestHandler/dllmain.cpp b/src/AspNetCoreModuleV2/OutOfProcessRequestHandler/dllmain.cpp
index d74571e953..d77c5c47d8 100644
--- a/src/AspNetCoreModuleV2/OutOfProcessRequestHandler/dllmain.cpp
+++ b/src/AspNetCoreModuleV2/OutOfProcessRequestHandler/dllmain.cpp
@@ -260,6 +260,8 @@ BOOL APIENTRY DllMain(HMODULE hModule,
break;
case DLL_PROCESS_DETACH:
g_fProcessDetach = TRUE;
+ FORWARDING_HANDLER::StaticTerminate();
+ ALLOC_CACHE_HANDLER::StaticTerminate();
DebugStop();
default:
break;
diff --git a/src/AspNetCoreModuleV2/RequestHandlerLib/environmentvariablehash.h b/src/AspNetCoreModuleV2/RequestHandlerLib/environmentvariablehash.h
index 8fa054f2a9..98bcd5ada4 100644
--- a/src/AspNetCoreModuleV2/RequestHandlerLib/environmentvariablehash.h
+++ b/src/AspNetCoreModuleV2/RequestHandlerLib/environmentvariablehash.h
@@ -76,6 +76,7 @@ private:
mutable LONG _cRefs;
};
+
class ENVIRONMENT_VAR_HASH : public HASH_TABLE
{
public:
@@ -129,3 +130,12 @@ private:
ENVIRONMENT_VAR_HASH(const ENVIRONMENT_VAR_HASH &);
void operator=(const ENVIRONMENT_VAR_HASH &);
};
+
+struct ENVIRONMENT_VAR_HASH_DELETER
+{
+ void operator ()(ENVIRONMENT_VAR_HASH* hashTable) const
+ {
+ hashTable->Clear();
+ delete hashTable;
+ }
+};
diff --git a/src/Microsoft.AspNetCore.Server.IntegrationTesting.IIS/IISDeployer.cs b/src/Microsoft.AspNetCore.Server.IntegrationTesting.IIS/IISDeployer.cs
index d2df4a8f8c..8c07bec312 100644
--- a/src/Microsoft.AspNetCore.Server.IntegrationTesting.IIS/IISDeployer.cs
+++ b/src/Microsoft.AspNetCore.Server.IntegrationTesting.IIS/IISDeployer.cs
@@ -341,7 +341,7 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting.IIS
throw new InvalidOperationException("Site not stopped yet");
}
- if (appPool.WorkerProcesses.Any(wp => wp.State == WorkerProcessState.Running ||
+ if (appPool.WorkerProcesses != null && appPool.WorkerProcesses.Any(wp => wp.State == WorkerProcessState.Running ||
wp.State == WorkerProcessState.Stopping))
{
throw new InvalidOperationException("WorkerProcess not stopped yet");
diff --git a/src/Microsoft.AspNetCore.Server.IntegrationTesting.IIS/IISDeployerBase.cs b/src/Microsoft.AspNetCore.Server.IntegrationTesting.IIS/IISDeployerBase.cs
index 5e6aabdadb..be6f39edec 100644
--- a/src/Microsoft.AspNetCore.Server.IntegrationTesting.IIS/IISDeployerBase.cs
+++ b/src/Microsoft.AspNetCore.Server.IntegrationTesting.IIS/IISDeployerBase.cs
@@ -100,7 +100,8 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting.IIS
private void AddWebConfigEnvironmentVariables(XElement element, string contentRoot)
{
var environmentVariables = element
- .RequiredElement("system.webServer")
+ .Descendants("system.webServer")
+ .Single()
.RequiredElement("aspNetCore")
.GetOrAdd("environmentVariables");
@@ -114,7 +115,8 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting.IIS
private void AddHandlerSettings(XElement element, string contentRoot)
{
var handlerSettings = element
- .RequiredElement("system.webServer")
+ .Descendants("system.webServer")
+ .Single()
.RequiredElement("aspNetCore")
.GetOrAdd("handlerSettings");
diff --git a/src/Microsoft.AspNetCore.Server.IntegrationTesting.IIS/WebConfigHelpers.cs b/src/Microsoft.AspNetCore.Server.IntegrationTesting.IIS/WebConfigHelpers.cs
index 589907657f..f920622568 100644
--- a/src/Microsoft.AspNetCore.Server.IntegrationTesting.IIS/WebConfigHelpers.cs
+++ b/src/Microsoft.AspNetCore.Server.IntegrationTesting.IIS/WebConfigHelpers.cs
@@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
+using System.Linq;
using System.Xml.Linq;
namespace Microsoft.AspNetCore.Server.IntegrationTesting.IIS
@@ -12,7 +13,8 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting.IIS
{
return (element, _) => {
element
- .GetOrAdd("system.webServer")
+ .Descendants("system.webServer")
+ .Single()
.GetOrAdd("aspNetCore")
.SetAttributeValue(key, value);
};
@@ -23,7 +25,8 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting.IIS
return (element, _) =>
{
element
- .GetOrAdd("system.webServer")
+ .Descendants("system.webServer")
+ .Single()
.GetOrAdd("handlers")
.GetOrAdd("add")
.SetAttributeValue(key, value);
diff --git a/test/Common.FunctionalTests/MultiApplicationTests.cs b/test/Common.FunctionalTests/MultiApplicationTests.cs
index a91dfa4d76..009c61f373 100644
--- a/test/Common.FunctionalTests/MultiApplicationTests.cs
+++ b/test/Common.FunctionalTests/MultiApplicationTests.cs
@@ -3,6 +3,7 @@
using System;
using System.IO;
+using System.Linq;
using System.Threading.Tasks;
using System.Xml.Linq;
using Microsoft.AspNetCore.Server.IIS.FunctionalTests.Utilities;
@@ -78,7 +79,8 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
var webConfigLocation = GetWebConfigLocation(directory);
XDocument webConfig = XDocument.Load(webConfigLocation);
webConfig.Root
- .GetOrAdd("system.webServer")
+ .Descendants("system.webServer")
+ .Single()
.GetOrAdd("aspNetCore")
.SetAttributeValue("hostingModel", model.ToString());
webConfig.Save(webConfigLocation);
diff --git a/tools/SetupTestEnvironment.ps1 b/tools/SetupTestEnvironment.ps1
new file mode 100644
index 0000000000..6fabf1704b
--- /dev/null
+++ b/tools/SetupTestEnvironment.ps1
@@ -0,0 +1,96 @@
+param($Mode)
+
+function Setup-appverif($application)
+{
+ appverif.exe -enable Exceptions Handles Heaps Leak Locks Memory Threadpool TLS SRWLock -for $application
+ $onlyLog = 0x181;
+ $codes = @(
+ # Exceptions
+ 0x650,
+ # Handles
+ 0x300, 0x301, 0x302, 0x303, 0x304, 0x305,
+ # Heaps
+ 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007, 0x008, 0x009, 0x00A, 0x00B, 0x00C, 0x00D, 0x00E, 0x00F, 0x010, 0x011, 0x012, 0x013, 0x014,
+ # Leak
+ 0x900, 0x901, 0x902, 0x903, 0x904, 0x905, 0x906,
+ # Locks
+ 0x200, 0x201, 0x202, 0x203, 0x204, 0x205, 0x206, 0x207, 0x208, 0x209, 0x210, 0x211, 0x212, 0x213, 0x214, 0x215,
+ # Memory
+ 0x600, 0x601, 0x602, 0x603, 0x604, 0x605, 0x606, 0x607, 0x608, 0x609, 0x60A, 0x60B, 0x60C, 0x60D, 0x60E, 0x60F, 0x610, 0x612, 0x613, 0x614, 0x615, 0x616, 0x617, 0x618, 0x619, 0x61A, 0x61B, 0x61C, 0x61D, 0x61E,
+ # SRWLock
+ 0x250, 0x251, 0x252, 0x253, 0x254, 0x255, 0x256, 0x257,
+ # TSL
+ 0x350, 0x351, 0x352,
+ # ThreadPool
+ 0x700, 0x701, 0x702, 0x703, 0x704, 0x705, 0x706, 0x707, 0x708, 0x709, 0x70A, 0x70B, 0x70C, 0x70D
+ );
+ appverif.exe -configure $codes -for $application -with ErrorReport=$onlyLog
+}
+
+function Shutdown-appverif($application)
+{
+ appverif.exe -export log -for $application -with To=$LogsFolder\$application.xml Log=0
+ appverif.exe -disable * -for $application
+}
+
+$DumpFolder = "$PSScriptRoot\..\artifacts\dumps"
+if (!(Test-Path $DumpFolder))
+{
+ New-Item $DumpFolder -ItemType Directory;
+}
+$DumpFolder = Resolve-Path $DumpFolder
+
+$LogsFolder = "$PSScriptRoot\..\artifacts\logs"
+if (!(Test-Path $LogsFolder))
+{
+ New-Item $LogsFolder -ItemType Directory;
+}
+$LogsFolder = Resolve-Path $LogsFolder
+
+$werHive = "HKLM:\SOFTWARE\Microsoft\Windows\Windows Error Reporting";
+$ldHive = "$werHive\LocalDumps";
+
+
+$cdb = "c:\Program Files (x86)\Windows Kits\10\Debuggers\x64\cdb.exe"
+if (!(Test-Path $cdb))
+{
+ $downloadedFile = [System.IO.Path]::GetTempFileName();
+ $downloadedFile = "$downloadedFile.exe";
+ Invoke-WebRequest -Uri "https://go.microsoft.com/fwlink/p/?linkid=870807" -OutFile $downloadedFile;
+ & $downloadedFile /features OptionId.WindowsDesktopDebuggers /norestart /q;
+}
+
+if ($Mode -eq "Setup")
+{
+ #Setup-appverif w3wp.exe
+ #Setup-appverif iisexpress.exe
+
+ if (!(Test-Path $ldHive ))
+ {
+ New-Item -Path $werHive -Name LocalDumps
+ }
+
+ New-ItemProperty $ldHive -Name "DumpFolder" -Value $DumpFolder -PropertyType "ExpandString" -Force;
+ New-ItemProperty $ldHive -Name "DumpCount" -Value 15 -PropertyType "DWORD" -Force;
+ New-ItemProperty $ldHive -Name "DumpType" -Value 2 -PropertyType "DWORD" -Force;
+
+ Restart-Service WerSvc
+}
+
+if ($Mode -eq "Shutdown")
+{
+ Remove-Item $ldHive -Recurse -Force
+
+ #Shutdown-appverif w3wp.exe
+ #Shutdown-appverif iisexpress.exe
+
+ foreach ($dump in (Get-ChildItem -Path $DumpFolder -Filter "*.dmp"))
+ {
+ if (Test-Path $cdb)
+ {
+ & $cdb -z $dump.FullName -y "https://msdl.microsoft.com/download/symbols" -c ".loadby sos coreclr;!sym noisy;.reload /f;.dumpcab -a $($dump.FullName).cab;q;"
+ }
+ }
+}
+
+Exit 0;
\ No newline at end of file
diff --git a/tools/stresstest.ps1 b/tools/stresstest.ps1
deleted file mode 100644
index 981c6fcf44..0000000000
--- a/tools/stresstest.ps1
+++ /dev/null
@@ -1,96 +0,0 @@
-##########################################################
-# NOTE:
-# For running test automation, following prerequisite required:
-#
-# 1. On Win7, powershell should be upgraded to 4.0
-# https://social.technet.microsoft.com/wiki/contents/articles/21016.how-to-install-windows-powershell-4-0.aspx
-# 2. url-rewrite should be installed
-# 3. makecert.exe tools should be available
-##########################################################
-
-# Replace aspnetcore.dll with the latest version
-copy C:\gitroot\AspNetCoreModule\artifacts\build\AspNetCore\bin\Release\x64\aspnetcore.dll "C:\Program Files\IIS Express"
-copy C:\gitroot\AspNetCoreModule\artifacts\build\AspNetCore\bin\Release\x64\aspnetcore.pdb "C:\Program Files\IIS Express"
-
-
-# Enable appverif for IISExpress.exe
-appverif /verify iisexpress.exe
-
-# Set the AspNetCoreModuleTest environment variable with the following command
-cd C:\gitroot\AspNetCoreModule\test\AspNetCoreModule.Test
-dotnet restore
-dotnet build
-$aspNetCoreModuleTest="C:\gitroot\AspNetCoreModule\test\AspNetCoreModule.Test\bin\Debug\net46"
-
-if (Test-Path (Join-Path $aspNetCoreModuleTest aspnetcoremodule.test.dll))
-{
- # Clean up applicationhost.config of IISExpress
- del $env:userprofile\documents\iisexpress\config\applicationhost.config -Confirm:$false -Force
- Start-Process "C:\Program Files\IIS Express\iisexpress.exe"
- Sleep 3
- Stop-Process -Name iisexpress
-
- # Create sites
- (1..50) | foreach { md ("C:\inetpub\wwwroot\AspnetCoreHandler_HelloWeb\foo" + $_ ) 2> out-null }
- (1..50) | foreach { copy C:\gitroot\AspNetCoreModule\test\StressTestWebRoot\web.config ("C:\inetpub\wwwroot\AspnetCoreHandler_HelloWeb\foo" + $_ ) }
- (1..50) | foreach {
- $path = ("C:\inetpub\wwwroot\AspnetCoreHandler_HelloWeb\foo" + $_ )
- $appPath = "/foo"+$_
- & "C:\Program Files\IIS Express\appcmd.exe" add app /site.name:"WebSite1" /path:$appPath /physicalPath:$path
- }
-
- <#(1..50) | foreach {
- $configpath = ("WebSite1/foo" + $_)
- $value = "C:\inetpub\wwwroot\AspnetCoreHandler_HelloWeb\foo" + $_ + ".exe"
- & "C:\Program Files\IIS Express\appcmd.exe" set config $configpath -section:system.webServer/aspNetCore /processPath:$value
- }
- (1..50) | foreach { copy C:\inetpub\wwwroot\AspnetCoreHandler_HelloWeb\foo.exe ("C:\inetpub\wwwroot\AspnetCoreHandler_HelloWeb\foo" + $_ +".exe") }
- (1..50) | foreach {
- $configpath = ("WebSite1/foo" + $_)
- $value = "%AspNetCoreModuleTest%\AspnetCoreApp_HelloWeb\foo" + $_ + ".exe"
- & "C:\Program Files\IIS Express\appcmd.exe" set config $configpath -section:system.webServer/aspNetCore /processPath:$value /apphostconfig:%AspNetCoreModuleTest%\config\applicationhost.config
-
- $value = "%AspNetCoreModuleTest%\AspnetCoreApp_HelloWeb\AutobahnTestServer.dll"
- & "C:\Program Files\IIS Express\appcmd.exe" set config $configpath -section:system.webServer/aspNetCore /arguments:$value /apphostconfig:%AspNetCoreModuleTest%\config\applicationhost.config
- }
- #>
-
- # Start IISExpress with running the below command
- &"C:\Program Files\Debugging Tools for Windows (x64)\windbg.exe" /g /G "C:\Program Files\IIS Express\iisexpress.exe"
-
-
- # 6. Start stress testing
- (1..10000) | foreach {
- if ($_ % 2 -eq 0)
- {
- ("Recycling backend only")
- stop-process -name dotnet
- (1..50) | foreach { del ("C:\inetpub\wwwroot\AspnetCoreHandler_HelloWeb\foo" + $_ + "\app_offline.htm") -confirm:$false -Force 2> out-null }
- stop-process -name dotnet
- }
- else
- {
- ("Recycling backedn + enabling appoffline ....")
- stop-process -name dotnet
- (1..50) | foreach { copy C:\gitroot\AspNetCoreModule\test\StressTestWebRoot\app_offline.htm ("C:\inetpub\wwwroot\AspnetCoreHandler_HelloWeb\foo" + $_ ) }
- }
- Sleep 1
-
- (1..10) | foreach {
- (1..50) | foreach {
- invoke-webrequest ("http://localhost:8080/foo"+$_) > $null
- }
- }
- }
-
-
- # Stress test idea
- # 1. Use Web Stress Tester
- # 2. Run stop-process -name dotnet
- # 3. Hit Q command to IISExpress console window
- # 4. Use app_offline.htm
- # 5. Save dummy web.config
-}
-
-// bp aspnetcore!FORWARDING_HANDLER::FORWARDING_HANDLER
-// bp aspnetcore!FORWARDING_HANDLER::~FORWARDING_HANDLER
\ No newline at end of file