merge release/2.2 into master

This commit is contained in:
Justin Kotalik 2018-07-30 14:04:01 -07:00
commit d4d6db80eb
22 changed files with 207 additions and 161 deletions

View File

@ -3,6 +3,8 @@ phases:
parameters: parameters:
agentOs: Windows agentOs: Windows
beforeBuild: beforeBuild:
- powershell: "git submodule update --init"
displayName: Update submodules
- powershell: "& ./tools/update_schema.ps1" - powershell: "& ./tools/update_schema.ps1"
displayName: Update ANCM schema displayName: Update ANCM schema
- powershell: Restart-Service w3svc - powershell: Restart-Service w3svc

View File

@ -237,6 +237,13 @@ Language=English
%1 %1
. .
Messageid=1035
SymbolicName=ASPNETCORE_EVENT_INPROCESS_THREAD_EXIT_STDOUT
Language=English
%1
.
; ;
;#endif // _ASPNETCORE_MODULE_MSG_H_ ;#endif // _ASPNETCORE_MODULE_MSG_H_
; ;

View File

@ -7,10 +7,10 @@
#include "requesthandler_config.h" #include "requesthandler_config.h"
#include "environmentvariablehelpers.h" #include "environmentvariablehelpers.h"
#include "utility.h" #include "utility.h"
#include "EventLog.h"
#include "SRWExclusiveLock.h" #include "SRWExclusiveLock.h"
#include "exceptions.h" #include "exceptions.h"
#include "LoggingHelpers.h" #include "LoggingHelpers.h"
#include "resources.h"
const LPCSTR IN_PROCESS_APPLICATION::s_exeLocationParameterName = "InProcessExeLocation"; const LPCSTR IN_PROCESS_APPLICATION::s_exeLocationParameterName = "InProcessExeLocation";
@ -220,7 +220,6 @@ IN_PROCESS_APPLICATION::SetCallbackHandles(
m_ShutdownHandlerContext = pvShutdownHandlerContext; m_ShutdownHandlerContext = pvShutdownHandlerContext;
m_AsyncCompletionHandler = async_completion_handler; m_AsyncCompletionHandler = async_completion_handler;
m_pLoggerProvider->NotifyStartupComplete();
// Can't check the std err handle as it isn't a critical error // Can't check the std err handle as it isn't a critical error
// Initialization complete // Initialization complete
UTILITY::LogEventF(g_hEventLog, UTILITY::LogEventF(g_hEventLog,
@ -498,11 +497,10 @@ Finished:
m_status = APPLICATION_STATUS::SHUTDOWN; m_status = APPLICATION_STATUS::SHUTDOWN;
m_fShutdownCalledFromManaged = TRUE; m_fShutdownCalledFromManaged = TRUE;
FreeLibrary(hModule); FreeLibrary(hModule);
m_pLoggerProvider->Stop();
if (!m_fShutdownCalledFromNative) if (!m_fShutdownCalledFromNative)
{ {
m_pLoggerProvider->NotifyStartupComplete();
LogErrorsOnMainExit(hr); LogErrorsOnMainExit(hr);
if (m_fInitialized) if (m_fInitialized)
{ {
@ -533,7 +531,7 @@ IN_PROCESS_APPLICATION::LogErrorsOnMainExit(
if (SUCCEEDED(struStdMsg.CopyA(straStdErrOutput.QueryStr()))) { if (SUCCEEDED(struStdMsg.CopyA(straStdErrOutput.QueryStr()))) {
UTILITY::LogEventF(g_hEventLog, UTILITY::LogEventF(g_hEventLog,
EVENTLOG_ERROR_TYPE, EVENTLOG_ERROR_TYPE,
ASPNETCORE_EVENT_INPROCESS_THREAD_EXIT, ASPNETCORE_EVENT_INPROCESS_THREAD_EXIT_STDOUT,
ASPNETCORE_EVENT_INPROCESS_THREAD_EXIT_STDOUT_MSG, ASPNETCORE_EVENT_INPROCESS_THREAD_EXIT_STDOUT_MSG,
m_pConfig->QueryApplicationPath()->QueryStr(), m_pConfig->QueryApplicationPath()->QueryStr(),
m_pConfig->QueryApplicationPhysicalPath()->QueryStr(), m_pConfig->QueryApplicationPhysicalPath()->QueryStr(),

View File

@ -18,8 +18,7 @@ register_callbacks(
_In_ PFN_SHUTDOWN_HANDLER shutdown_handler, _In_ PFN_SHUTDOWN_HANDLER shutdown_handler,
_In_ PFN_ASYNC_COMPLETION_HANDLER async_completion_handler, _In_ PFN_ASYNC_COMPLETION_HANDLER async_completion_handler,
_In_ VOID* pvRequstHandlerContext, _In_ VOID* pvRequstHandlerContext,
_In_ VOID* pvShutdownHandlerContext, _In_ VOID* pvShutdownHandlerContext
_Out_ BOOL* pfResetStandardStreams
) )
{ {
if (pInProcessApplication == NULL) if (pInProcessApplication == NULL)
@ -34,7 +33,6 @@ register_callbacks(
pvRequstHandlerContext, pvRequstHandlerContext,
pvShutdownHandlerContext pvShutdownHandlerContext
); );
*pfResetStandardStreams = !pInProcessApplication->QueryConfig()->QueryStdoutLogEnabled();
return S_OK; return S_OK;
} }

View File

@ -7,48 +7,20 @@
#include "utility.h" #include "utility.h"
#include "exceptions.h" #include "exceptions.h"
#include "debugutil.h" #include "debugutil.h"
#include "SRWExclusiveLock.h"
FileOutputManager::FileOutputManager() : FileOutputManager::FileOutputManager() :
m_hLogFileHandle(INVALID_HANDLE_VALUE), m_hLogFileHandle(INVALID_HANDLE_VALUE),
m_fdPreviousStdOut(-1), m_fdPreviousStdOut(-1),
m_fdPreviousStdErr(-1) m_fdPreviousStdErr(-1),
m_disposed(false)
{ {
InitializeSRWLock(&m_srwLock);
} }
FileOutputManager::~FileOutputManager() FileOutputManager::~FileOutputManager()
{ {
HANDLE handle = NULL; Stop();
WIN32_FIND_DATA fileData;
if (m_hLogFileHandle != INVALID_HANDLE_VALUE)
{
m_Timer.CancelTimer();
}
// delete empty log file
handle = FindFirstFile(m_struLogFilePath.QueryStr(), &fileData);
if (handle != INVALID_HANDLE_VALUE &&
handle != NULL &&
fileData.nFileSizeHigh == 0 &&
fileData.nFileSizeLow == 0) // skip check of nFileSizeHigh
{
FindClose(handle);
// no need to check whether the deletion succeeds
// as nothing can be done
DeleteFile(m_struLogFilePath.QueryStr());
}
if (m_fdPreviousStdOut >= 0)
{
LOG_LAST_ERROR_IF(SetStdHandle(STD_OUTPUT_HANDLE, (HANDLE)_get_osfhandle(m_fdPreviousStdOut)));
LOG_INFOF("Restoring original stdout: %d", m_fdPreviousStdOut);
}
if (m_fdPreviousStdErr >= 0)
{
LOG_LAST_ERROR_IF(SetStdHandle(STD_ERROR_HANDLE, (HANDLE)_get_osfhandle(m_fdPreviousStdErr)));
LOG_INFOF("Restoring original stderr: %d", m_fdPreviousStdOut);
}
} }
HRESULT HRESULT
@ -100,8 +72,6 @@ bool FileOutputManager::GetStdOutContent(STRA* struStdOutput)
} }
} }
LOG_INFOF("First 4KB captured by stdout: %s", pzFileContents);
return fLogged; return fLogged;
} }
@ -174,3 +144,52 @@ FileOutputManager::Start()
return S_OK; return S_OK;
} }
HRESULT
FileOutputManager::Stop()
{
if (m_disposed)
{
return S_OK;
}
SRWExclusiveLock lock(m_srwLock);
if (m_disposed)
{
return S_OK;
}
m_disposed = true;
HANDLE handle = NULL;
WIN32_FIND_DATA fileData;
if (m_hLogFileHandle != INVALID_HANDLE_VALUE)
{
m_Timer.CancelTimer();
}
// delete empty log file
handle = FindFirstFile(m_struLogFilePath.QueryStr(), &fileData);
if (handle != INVALID_HANDLE_VALUE &&
handle != NULL &&
fileData.nFileSizeHigh == 0 &&
fileData.nFileSizeLow == 0) // skip check of nFileSizeHigh
{
FindClose(handle);
LOG_LAST_ERROR_IF(!DeleteFile(m_struLogFilePath.QueryStr()));
}
if (m_fdPreviousStdOut >= 0)
{
LOG_LAST_ERROR_IF(!SetStdHandle(STD_OUTPUT_HANDLE, (HANDLE)_get_osfhandle(m_fdPreviousStdOut)));
LOG_INFOF("Restoring original stdout: %d", m_fdPreviousStdOut);
}
if (m_fdPreviousStdErr >= 0)
{
LOG_LAST_ERROR_IF(!SetStdHandle(STD_ERROR_HANDLE, (HANDLE)_get_osfhandle(m_fdPreviousStdErr)));
LOG_INFOF("Restoring original stderr: %d", m_fdPreviousStdOut);
}
return S_OK;
}

View File

@ -19,7 +19,7 @@ public:
virtual bool GetStdOutContent(STRA* struStdOutput) override; virtual bool GetStdOutContent(STRA* struStdOutput) override;
virtual HRESULT Start() override; virtual HRESULT Start() override;
virtual void NotifyStartupComplete() override {}; virtual HRESULT Stop() override;
private: private:
HandleWrapper<InvalidHandleTraits> m_hLogFileHandle; HandleWrapper<InvalidHandleTraits> m_hLogFileHandle;
@ -29,5 +29,7 @@ private:
STRU m_struLogFilePath; STRU m_struLogFilePath;
int m_fdPreviousStdOut; int m_fdPreviousStdOut;
int m_fdPreviousStdErr; int m_fdPreviousStdErr;
BOOL m_disposed;
SRWLOCK m_srwLock;
}; };

View File

@ -14,12 +14,12 @@ public:
virtual virtual
~IOutputManager() {}; ~IOutputManager() {};
virtual
void
NotifyStartupComplete() = 0;
virtual virtual
bool bool
GetStdOutContent(STRA* struStdOutput) = 0; GetStdOutContent(STRA* struStdOutput) = 0;
virtual
HRESULT
Stop() = 0;
}; };

View File

@ -15,12 +15,12 @@ public:
HRESULT Start() HRESULT Start()
{ {
// The process has console, e.g., IIS Express scenario
return S_OK; return S_OK;
} }
void NotifyStartupComplete() HRESULT Stop()
{ {
return S_OK;
} }
bool GetStdOutContent(STRA*) bool GetStdOutContent(STRA*)

View File

@ -14,7 +14,7 @@ PipeOutputManager::PipeOutputManager() :
m_hErrReadPipe(INVALID_HANDLE_VALUE), m_hErrReadPipe(INVALID_HANDLE_VALUE),
m_hErrWritePipe(INVALID_HANDLE_VALUE), m_hErrWritePipe(INVALID_HANDLE_VALUE),
m_hErrThread(NULL), m_hErrThread(NULL),
m_fDisposed(FALSE), m_disposed(FALSE),
m_fdPreviousStdOut(-1), m_fdPreviousStdOut(-1),
m_fdPreviousStdErr(-1) m_fdPreviousStdErr(-1)
{ {
@ -23,26 +23,61 @@ PipeOutputManager::PipeOutputManager() :
PipeOutputManager::~PipeOutputManager() PipeOutputManager::~PipeOutputManager()
{ {
StopOutputRedirection(); Stop();
} }
VOID HRESULT PipeOutputManager::Start()
PipeOutputManager::StopOutputRedirection() {
SECURITY_ATTRIBUTES saAttr = { 0 };
HANDLE hStdErrReadPipe;
HANDLE hStdErrWritePipe;
m_fdPreviousStdOut = _dup(_fileno(stdout));
LOG_IF_DUPFAIL(m_fdPreviousStdOut);
m_fdPreviousStdErr = _dup(_fileno(stderr));
LOG_IF_DUPFAIL(m_fdPreviousStdErr);
RETURN_LAST_ERROR_IF(!CreatePipe(&hStdErrReadPipe, &hStdErrWritePipe, &saAttr, 0 /*nSize*/));
// TODO this still doesn't redirect calls in native, like wprintf
RETURN_LAST_ERROR_IF(!SetStdHandle(STD_ERROR_HANDLE, hStdErrWritePipe));
RETURN_LAST_ERROR_IF(!SetStdHandle(STD_OUTPUT_HANDLE, hStdErrWritePipe));
m_hErrReadPipe = hStdErrReadPipe;
m_hErrWritePipe = hStdErrWritePipe;
// Read the stderr handle on a separate thread until we get 4096 bytes.
m_hErrThread = CreateThread(
NULL, // default security attributes
0, // default stack size
(LPTHREAD_START_ROUTINE)ReadStdErrHandle,
this, // thread function arguments
0, // default creation flags
NULL); // receive thread identifier
RETURN_LAST_ERROR_IF_NULL(m_hErrThread);
return S_OK;
}
HRESULT PipeOutputManager::Stop()
{ {
DWORD dwThreadStatus = 0; DWORD dwThreadStatus = 0;
STRA straStdOutput; STRA straStdOutput;
if (m_fDisposed) if (m_disposed)
{ {
return; return S_OK;
} }
SRWExclusiveLock lock(m_srwLock); SRWExclusiveLock lock(m_srwLock);
if (m_fDisposed) if (m_disposed)
{ {
return; return S_OK;
} }
m_fDisposed = true; m_disposed = true;
fflush(stdout); fflush(stdout);
fflush(stderr); fflush(stderr);
@ -115,40 +150,6 @@ PipeOutputManager::StopOutputRedirection()
// Need to flush contents for the new stdout and stderr // Need to flush contents for the new stdout and stderr
_flushall(); _flushall();
} }
}
HRESULT PipeOutputManager::Start()
{
SECURITY_ATTRIBUTES saAttr = { 0 };
HANDLE hStdErrReadPipe;
HANDLE hStdErrWritePipe;
m_fdPreviousStdOut = _dup(_fileno(stdout));
LOG_IF_DUPFAIL(m_fdPreviousStdOut);
m_fdPreviousStdErr = _dup(_fileno(stderr));
LOG_IF_DUPFAIL(m_fdPreviousStdErr);
RETURN_LAST_ERROR_IF(!CreatePipe(&hStdErrReadPipe, &hStdErrWritePipe, &saAttr, 0 /*nSize*/));
// TODO this still doesn't redirect calls in native, like wprintf
RETURN_LAST_ERROR_IF(!SetStdHandle(STD_ERROR_HANDLE, hStdErrWritePipe));
RETURN_LAST_ERROR_IF(!SetStdHandle(STD_OUTPUT_HANDLE, hStdErrWritePipe));
m_hErrReadPipe = hStdErrReadPipe;
m_hErrWritePipe = hStdErrWritePipe;
// Read the stderr handle on a separate thread until we get 4096 bytes.
m_hErrThread = CreateThread(
NULL, // default security attributes
0, // default stack size
(LPTHREAD_START_ROUTINE)ReadStdErrHandle,
this, // thread function arguments
0, // default creation flags
NULL); // receive thread identifier
RETURN_LAST_ERROR_IF_NULL(m_hErrThread);
return S_OK; return S_OK;
} }
@ -163,16 +164,17 @@ PipeOutputManager::ReadStdErrHandle(
pLoggingProvider->ReadStdErrHandleInternal(); pLoggingProvider->ReadStdErrHandleInternal();
} }
bool PipeOutputManager::GetStdOutContent(STRA* struStdOutput) bool PipeOutputManager::GetStdOutContent(STRA* straStdOutput)
{ {
bool fLogged = false; bool fLogged = false;
if (m_dwStdErrReadTotal > 0) if (m_dwStdErrReadTotal > 0)
{ {
if (SUCCEEDED(struStdOutput->Copy(m_pzFileContents, m_dwStdErrReadTotal))) if (SUCCEEDED(straStdOutput->Copy(m_pzFileContents, m_dwStdErrReadTotal)))
{ {
fLogged = TRUE; fLogged = TRUE;
} }
} }
return fLogged; return fLogged;
} }
@ -194,13 +196,19 @@ PipeOutputManager::ReadStdErrHandleInternal(
} }
else if (GetLastError() == ERROR_BROKEN_PIPE) else if (GetLastError() == ERROR_BROKEN_PIPE)
{ {
break; return;
}
}
char tempBuffer[MAX_PIPE_READ_SIZE];
while (true)
{
if (ReadFile(m_hErrReadPipe, tempBuffer, MAX_PIPE_READ_SIZE, &dwNumBytesRead, NULL))
{
}
else if (GetLastError() == ERROR_BROKEN_PIPE)
{
return;
} }
} }
} }
VOID
PipeOutputManager::NotifyStartupComplete()
{
StopOutputRedirection();
}

View File

@ -13,30 +13,26 @@ public:
PipeOutputManager(); PipeOutputManager();
~PipeOutputManager(); ~PipeOutputManager();
// Inherited via ILoggerProvider
virtual HRESULT Start() override; virtual HRESULT Start() override;
virtual void NotifyStartupComplete() override; virtual HRESULT Stop() override;
// Inherited via IOutputManager
virtual bool GetStdOutContent(STRA* struStdOutput) override; virtual bool GetStdOutContent(STRA* struStdOutput) override;
// Thread functions
VOID ReadStdErrHandleInternal(VOID); VOID ReadStdErrHandleInternal(VOID);
static static
VOID ReadStdErrHandle(LPVOID pContext); VOID ReadStdErrHandle(LPVOID pContext);
private: private:
VOID StopOutputRedirection();
HANDLE m_hErrReadPipe; HANDLE m_hErrReadPipe;
HANDLE m_hErrWritePipe; HANDLE m_hErrWritePipe;
STRU m_struLogFilePath; STRU m_struLogFilePath;
HANDLE m_hErrThread; HANDLE m_hErrThread;
CHAR m_pzFileContents[MAX_PIPE_READ_SIZE] = { 0 }; CHAR m_pzFileContents[MAX_PIPE_READ_SIZE] = { 0 };
DWORD m_dwStdErrReadTotal; DWORD m_dwStdErrReadTotal;
BOOL m_fDisposed;
SRWLOCK m_srwLock; SRWLOCK m_srwLock;
int m_fdPreviousStdOut; int m_fdPreviousStdOut;
int m_fdPreviousStdErr; int m_fdPreviousStdErr;
BOOL m_disposed;
}; };

View File

@ -38,33 +38,7 @@ namespace Microsoft.AspNetCore.Server.IIS.Core
shutdownHandler, shutdownHandler,
onAsyncCompletion, onAsyncCompletion,
requestContext, requestContext,
shutdownContext, shutdownContext);
out var resetStandardStreams);
if (resetStandardStreams)
{
ResetStdOutHandles();
}
}
private static void ResetStdOutHandles()
{
// By using the PipeOutputRedirection, after calling RegisterCallbacks,
// stdout and stderr will be redirected to NULL. However, if something wrote
// to stdout before redirecting, (like a Console.WriteLine during startup),
// we need to call Console.Set* to pick up the modified consoles outputs.
Console.SetOut(CreateStreamWriter(Console.OpenStandardOutput()));
Console.SetError(CreateStreamWriter(Console.OpenStandardError()));
}
private static StreamWriter CreateStreamWriter(Stream stdStream)
{
return new StreamWriter(
stdStream,
encoding: Console.OutputEncoding,
bufferSize: 256,
leaveOpen: true)
{ AutoFlush = true };
} }
public void Dispose() public void Dispose()

View File

@ -59,8 +59,7 @@ namespace Microsoft.AspNetCore.Server.IIS
PFN_SHUTDOWN_HANDLER shutdownCallback, PFN_SHUTDOWN_HANDLER shutdownCallback,
PFN_ASYNC_COMPLETION asyncCallback, PFN_ASYNC_COMPLETION asyncCallback,
IntPtr pvRequestContext, IntPtr pvRequestContext,
IntPtr pvShutdownContext, IntPtr pvShutdownContext);
out bool resetStandardStreams);
[DllImport(AspNetCoreModuleDll)] [DllImport(AspNetCoreModuleDll)]
private static extern unsafe int http_write_response_bytes(IntPtr pInProcessHandler, HttpApiTypes.HTTP_DATA_CHUNK* pDataChunks, int nChunks, out bool fCompletionExpected); private static extern unsafe int http_write_response_bytes(IntPtr pInProcessHandler, HttpApiTypes.HTTP_DATA_CHUNK* pDataChunks, int nChunks, out bool fCompletionExpected);
@ -147,10 +146,9 @@ namespace Microsoft.AspNetCore.Server.IIS
PFN_SHUTDOWN_HANDLER shutdownCallback, PFN_SHUTDOWN_HANDLER shutdownCallback,
PFN_ASYNC_COMPLETION asyncCallback, PFN_ASYNC_COMPLETION asyncCallback,
IntPtr pvRequestContext, IntPtr pvRequestContext,
IntPtr pvShutdownContext, IntPtr pvShutdownContext)
out bool resetStandardStreams)
{ {
Validate(register_callbacks(pInProcessApplication, requestCallback, shutdownCallback, asyncCallback, pvRequestContext, pvShutdownContext, out resetStandardStreams)); Validate(register_callbacks(pInProcessApplication, requestCallback, shutdownCallback, asyncCallback, pvRequestContext, pvShutdownContext));
} }
public static unsafe int HttpWriteResponseBytes(IntPtr pInProcessHandler, HttpApiTypes.HTTP_DATA_CHUNK* pDataChunks, int nChunks, out bool fCompletionExpected) public static unsafe int HttpWriteResponseBytes(IntPtr pInProcessHandler, HttpApiTypes.HTTP_DATA_CHUNK* pDataChunks, int nChunks, out bool fCompletionExpected)

View File

@ -65,7 +65,7 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting
} }
AddTemporaryAppHostConfig(); AddTemporaryAppHostConfig();
var apppool = ConfigureAppPool(contentRoot); ConfigureAppPool(contentRoot);
ConfigureSite(contentRoot, port); ConfigureSite(contentRoot, port);
@ -73,11 +73,11 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting
_serverManager.CommitChanges(); _serverManager.CommitChanges();
await WaitUntilSiteStarted(apppool); await WaitUntilSiteStarted();
} }
} }
private async Task WaitUntilSiteStarted(ApplicationPool appPool) private async Task WaitUntilSiteStarted()
{ {
var sw = Stopwatch.StartNew(); var sw = Stopwatch.StartNew();
@ -85,12 +85,19 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting
{ {
try try
{ {
var site = _serverManager.Sites.FirstOrDefault(s => s.Name.Equals(WebSiteName)); var serverManager = new ServerManager();
var appPool = serverManager.ApplicationPools.FirstOrDefault(s => s.Name.Equals(AppPoolName));
var site = serverManager.Sites.FirstOrDefault(s => s.Name.Equals(WebSiteName));
if (site.State == ObjectState.Started) if (site.State == ObjectState.Started)
{ {
_logger.LogInformation($"Site {WebSiteName} has started."); var workerProcess = appPool.WorkerProcesses.SingleOrDefault();
return; if (workerProcess != null)
{
HostProcess = Process.GetProcessById(workerProcess.ProcessId);
_logger.LogInformation($"Site {WebSiteName} has started.");
return;
}
} }
else if (site.State != ObjectState.Starting) else if (site.State != ObjectState.Starting)
{ {
@ -99,7 +106,7 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting
_logger.LogInformation($"Tried to start site, state: {state.ToString()}"); _logger.LogInformation($"Tried to start site, state: {state.ToString()}");
} }
} }
catch (COMException comException) catch (Exception ex) when (ex is DllNotFoundException || (ex is COMException && (uint)ex.HResult == 0x800710D8) )
{ {
// Accessing the site.State property while the site // Accessing the site.State property while the site
// is starting up returns the COMException // is starting up returns the COMException
@ -107,7 +114,6 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting
// (Exception from HRESULT: 0x800710D8) // (Exception from HRESULT: 0x800710D8)
// This also means the site is not started yet, so catch and retry // This also means the site is not started yet, so catch and retry
// after waiting. // after waiting.
_logger.LogWarning($"ComException: {comException.Message}");
} }
await Task.Delay(_retryDelay); await Task.Delay(_retryDelay);
@ -123,11 +129,15 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting
return; return;
} }
RestoreAppHostConfig(); StopSite();
StopAppPool();
_serverManager.CommitChanges(); _serverManager.CommitChanges();
await WaitUntilSiteStopped(); await WaitUntilSiteStopped();
RestoreAppHostConfig();
} }
private async Task WaitUntilSiteStopped() private async Task WaitUntilSiteStopped()
@ -146,8 +156,11 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting
{ {
if (site.State == ObjectState.Stopped) if (site.State == ObjectState.Stopped)
{ {
_logger.LogInformation($"Site {WebSiteName} has stopped successfully."); if (HostProcess.HasExited)
return; {
_logger.LogInformation($"Site {WebSiteName} has stopped successfully.");
return;
}
} }
} }
catch (COMException) catch (COMException)
@ -276,6 +289,20 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting
return config; return config;
} }
private void StopSite()
{
var site = _serverManager.Sites.Where(sites => sites.Name == WebSiteName).SingleOrDefault();
site.Stop();
}
private void StopAppPool()
{
var appPool = _serverManager.ApplicationPools.Where(pool => pool.Name == AppPoolName).SingleOrDefault();
appPool.Stop();
}
private void SetGlobalModuleSection(Configuration config, string dllRoot) private void SetGlobalModuleSection(Configuration config, string dllRoot)
{ {
var ancmFile = GetAncmLocation(dllRoot); var ancmFile = GetAncmLocation(dllRoot);

View File

@ -106,7 +106,11 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting.IIS
5, 5,
200); 200);
Logger.LogInformation($"Found debug log file: {file}"); if (arr.Length == 0)
{
Logger.LogWarning($"{file} is empty.");
}
foreach (var line in arr) foreach (var line in arr)
{ {
Logger.LogInformation(line); Logger.LogInformation(line);

View File

@ -68,7 +68,6 @@
<section name="httpTracing" overrideModeDefault="Deny" /> <section name="httpTracing" overrideModeDefault="Deny" />
<section name="isapiFilters" allowDefinition="MachineToApplication" overrideModeDefault="Deny" /> <section name="isapiFilters" allowDefinition="MachineToApplication" overrideModeDefault="Deny" />
<section name="modules" allowDefinition="MachineToApplication" overrideModeDefault="Deny" /> <section name="modules" allowDefinition="MachineToApplication" overrideModeDefault="Deny" />
<section name="applicationInitialization" allowDefinition="MachineToApplication" overrideModeDefault="Allow" />
<section name="odbcLogging" overrideModeDefault="Deny" /> <section name="odbcLogging" overrideModeDefault="Deny" />
<sectionGroup name="security"> <sectionGroup name="security">
<section name="access" overrideModeDefault="Deny" /> <section name="access" overrideModeDefault="Deny" />

View File

@ -108,6 +108,7 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
public async Task CheckStdoutLoggingToPipe_DoesNotCrashProcess(string path) public async Task CheckStdoutLoggingToPipe_DoesNotCrashProcess(string path)
{ {
var deploymentParameters = Helpers.GetBaseDeploymentParameters(publish: true); var deploymentParameters = Helpers.GetBaseDeploymentParameters(publish: true);
deploymentParameters.GracefulShutdown = true;
var deploymentResult = await DeployAsync(deploymentParameters); var deploymentResult = await DeployAsync(deploymentParameters);
await Helpers.AssertStarts(deploymentResult, path); await Helpers.AssertStarts(deploymentResult, path);
@ -126,6 +127,8 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
public async Task CheckStdoutLoggingToPipeWithFirstWrite(string path) public async Task CheckStdoutLoggingToPipeWithFirstWrite(string path)
{ {
var deploymentParameters = Helpers.GetBaseDeploymentParameters(publish: true); var deploymentParameters = Helpers.GetBaseDeploymentParameters(publish: true);
deploymentParameters.GracefulShutdown = true;
var firstWriteString = path + path; var firstWriteString = path + path;
deploymentParameters.WebConfigBasedEnvironmentVariables["ASPNETCORE_INPROCESS_INITIAL_WRITE"] = firstWriteString; deploymentParameters.WebConfigBasedEnvironmentVariables["ASPNETCORE_INPROCESS_INITIAL_WRITE"] = firstWriteString;

View File

@ -0,0 +1,17 @@
// 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 Microsoft.AspNetCore.Server.IntegrationTesting;
using Microsoft.AspNetCore.Testing.xunit;
namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
{
[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Method)]
public sealed class SkipInVSTSAttribute : Attribute, ITestCondition
{
public bool IsMet => string.IsNullOrEmpty(Environment.GetEnvironmentVariable("SYSTEM_TASKDEFINITIONSURI"));
public string SkipReason => "Running in VSTS";
}
}

View File

@ -29,9 +29,6 @@ namespace PipeOutputManagerTests
PipeOutputManager* pManager = new PipeOutputManager(); PipeOutputManager* pManager = new PipeOutputManager();
ASSERT_EQ(S_OK, pManager->Start()); ASSERT_EQ(S_OK, pManager->Start());
pManager->NotifyStartupComplete();
} }
TEST(PipeManagerOutputTest, SetInvalidHandlesForErrAndOut) TEST(PipeManagerOutputTest, SetInvalidHandlesForErrAndOut)
@ -47,8 +44,6 @@ namespace PipeOutputManagerTests
PipeOutputManager* pManager = new PipeOutputManager(); PipeOutputManager* pManager = new PipeOutputManager();
ASSERT_EQ(S_OK, pManager->Start()); ASSERT_EQ(S_OK, pManager->Start());
pManager->NotifyStartupComplete();
_dup2(m_fdPreviousStdOut, _fileno(stdout)); _dup2(m_fdPreviousStdOut, _fileno(stdout));
_dup2(m_fdPreviousStdErr, _fileno(stderr)); _dup2(m_fdPreviousStdErr, _fileno(stderr));

View File

@ -30,7 +30,6 @@
<None Include="$(MSBuildThisFileDirectory)..\..\src\AspNetCoreModuleV2\AspNetCore\bin\$(Configuration)\x64\aspnetcorev2.pdb" CopyToOutputDirectory="PreserveNewest" Visible="true" Link="%(FileName)%(Extension)" /> <None Include="$(MSBuildThisFileDirectory)..\..\src\AspNetCoreModuleV2\AspNetCore\bin\$(Configuration)\x64\aspnetcorev2.pdb" CopyToOutputDirectory="PreserveNewest" Visible="true" Link="%(FileName)%(Extension)" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Server.IntegrationTesting" Version="$(MicrosoftAspNetCoreServerIntegrationTestingPackageVersion)" /> <PackageReference Include="Microsoft.AspNetCore.Server.IntegrationTesting" Version="$(MicrosoftAspNetCoreServerIntegrationTestingPackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Hosting" Version="$(MicrosoftAspNetCoreHostingPackageVersion)" /> <PackageReference Include="Microsoft.AspNetCore.Hosting" Version="$(MicrosoftAspNetCoreHostingPackageVersion)" />

View File

@ -7,5 +7,4 @@ using Xunit;
[assembly: CollectionBehavior(DisableTestParallelization = true)] [assembly: CollectionBehavior(DisableTestParallelization = true)]
[assembly: RequiresIIS] [assembly: RequiresIIS]
[assembly: OSSkipCondition(OperatingSystems.Windows, WindowsVersions.Win7, SkipReason = "https://github.com/aspnet/IISIntegration/issues/1069")]

View File

@ -18,6 +18,7 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
// So these tests always have to use ports in this range, and we can't rely on OS-allocated ports without a whole lot of ceremony around // So these tests always have to use ports in this range, and we can't rely on OS-allocated ports without a whole lot of ceremony around
// creating self-signed certificates and registering SSL bindings with HTTP.sys // creating self-signed certificates and registering SSL bindings with HTTP.sys
// Test specific to IISExpress // Test specific to IISExpress
[SkipInVSTS]
public class HttpsTest : IISFunctionalTestBase public class HttpsTest : IISFunctionalTestBase
{ {
public HttpsTest(ITestOutputHelper output) : base(output) public HttpsTest(ITestOutputHelper output) : base(output)