From 0af3bef0fe75c7ff1b98680a9b568ba488b011b9 Mon Sep 17 00:00:00 2001 From: Justin Kotalik Date: Fri, 27 Jul 2018 17:32:01 -0700 Subject: [PATCH 1/5] Fix win7 test failures. (#1109) --- .../IISApplication.cs | 3 +-- test/Common.FunctionalTests/AppHostConfig/IIS.config | 1 - test/IIS.FunctionalTests/Properties/AssemblyInfo.cs | 1 - 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/Microsoft.AspNetCore.Server.IntegrationTesting.IIS/IISApplication.cs b/src/Microsoft.AspNetCore.Server.IntegrationTesting.IIS/IISApplication.cs index b83e7aa4df..bf0c338efc 100644 --- a/src/Microsoft.AspNetCore.Server.IntegrationTesting.IIS/IISApplication.cs +++ b/src/Microsoft.AspNetCore.Server.IntegrationTesting.IIS/IISApplication.cs @@ -99,7 +99,7 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting _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 // is starting up returns the COMException @@ -107,7 +107,6 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting // (Exception from HRESULT: 0x800710D8) // This also means the site is not started yet, so catch and retry // after waiting. - _logger.LogWarning($"ComException: {comException.Message}"); } await Task.Delay(_retryDelay); diff --git a/test/Common.FunctionalTests/AppHostConfig/IIS.config b/test/Common.FunctionalTests/AppHostConfig/IIS.config index c8c4848e25..624edf91ca 100644 --- a/test/Common.FunctionalTests/AppHostConfig/IIS.config +++ b/test/Common.FunctionalTests/AppHostConfig/IIS.config @@ -68,7 +68,6 @@
-
diff --git a/test/IIS.FunctionalTests/Properties/AssemblyInfo.cs b/test/IIS.FunctionalTests/Properties/AssemblyInfo.cs index c6007ab5fe..9941a6b5a5 100644 --- a/test/IIS.FunctionalTests/Properties/AssemblyInfo.cs +++ b/test/IIS.FunctionalTests/Properties/AssemblyInfo.cs @@ -7,5 +7,4 @@ using Xunit; [assembly: CollectionBehavior(DisableTestParallelization = true)] [assembly: RequiresIIS] -[assembly: OSSkipCondition(OperatingSystems.Windows, WindowsVersions.Win7, SkipReason = "https://github.com/aspnet/IISIntegration/issues/1069")] From b7e26fed9983b4ab5b60e76a7ae76c7a4f251a78 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 29 Jul 2018 12:15:13 -0700 Subject: [PATCH 2/5] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 57 ++++++++++++++++++++-------------------- korebuild-lock.txt | 4 +-- 2 files changed, 31 insertions(+), 30 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 9dc782a008..fe40c919f6 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -1,41 +1,41 @@ - + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) 0.10.13 - 2.2.0-preview1-17099 - 2.2.0-preview1-34755 - 2.2.0-preview1-34755 - 2.2.0-preview1-34755 - 2.2.0-preview1-34755 - 2.2.0-preview1-34755 - 2.2.0-preview1-34755 - 2.2.0-preview1-34755 - 2.2.0-preview1-34755 - 2.2.0-preview1-34755 - 0.6.0-a-preview1-IISVariants-17101 - 2.2.0-preview1-34755 - 2.2.0-preview1-34755 - 2.2.0-preview1-34755 - 2.2.0-preview1-34755 + 2.2.0-preview1-17102 + 2.2.0-preview1-34823 + 2.2.0-preview1-34823 + 2.2.0-preview1-34823 + 2.2.0-preview1-34823 + 2.2.0-preview1-34823 + 2.2.0-preview1-34823 + 2.2.0-preview1-34823 + 2.2.0-preview1-34823 + 2.2.0-preview1-34823 + 0.6.0-preview1-34823 + 2.2.0-preview1-34823 + 2.2.0-preview1-34823 + 2.2.0-preview1-34823 + 2.2.0-preview1-34823 15.6.82 15.6.82 - 2.2.0-preview1-34755 - 2.2.0-preview1-34755 - 2.2.0-preview1-34755 - 2.2.0-preview1-34755 - 2.2.0-preview1-34755 - 2.2.0-preview1-34755 - 2.2.0-preview1-34755 - 2.2.0-preview1-34755 - 2.2.0-preview1-34755 - 2.2.0-preview1-34755 + 2.2.0-preview1-34823 + 2.2.0-preview1-34823 + 2.2.0-preview1-34823 + 2.2.0-preview1-34823 + 2.2.0-preview1-34823 + 2.2.0-preview1-34823 + 2.2.0-preview1-34823 + 2.2.0-preview1-34823 + 2.2.0-preview1-34823 + 2.2.0-preview1-34823 2.0.9 2.1.2 2.2.0-preview1-26618-02 1.0.1 - 2.2.0-preview1-34755 + 2.2.0-preview1-34823 15.6.1 11.1.0 2.0.3 @@ -49,7 +49,8 @@ 4.5.0 9.0.1 2.3.1 - 2.4.0-rc.1.build4038 + 2.4.0 + diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 8b9d17825f..28cd6a5b03 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-17099 -commithash:263ed1db9866b6b419b1f5d5189a712aa218acb3 +version:2.2.0-preview1-17102 +commithash:e7e2b5a97ca92cfc6acc4def534cb0901a6d1eb9 From 41493f01e31c9bd9ed39cc8acbbb99ca5193a379 Mon Sep 17 00:00:00 2001 From: Justin Kotalik Date: Sun, 29 Jul 2018 23:25:32 -0700 Subject: [PATCH 3/5] Don't stop redirect stdout/stderr after startup is done. (#1067) --- .../CommonLib/aspnetcore_msg.mc | 7 ++ .../inprocessapplication.cpp | 8 +- .../managedexports.cpp | 4 +- .../RequestHandlerLib/FileOutputManager.cpp | 89 ++++++++------ .../RequestHandlerLib/FileOutputManager.h | 4 +- .../RequestHandlerLib/IOutputManager.h | 8 +- .../RequestHandlerLib/NullOutputManager.h | 4 +- .../RequestHandlerLib/PipeOutputManager.cpp | 112 ++++++++++-------- .../RequestHandlerLib/PipeOutputManager.h | 10 +- .../Core/IISNativeApplication.cs | 28 +---- .../NativeMethods.cs | 8 +- .../Inprocess/LoggingTests.cs | 3 + .../CommonLibTests/PipeOutputManagerTests.cpp | 5 - .../IIS.FunctionalTests.csproj | 1 - 14 files changed, 144 insertions(+), 147 deletions(-) diff --git a/src/AspNetCoreModuleV2/CommonLib/aspnetcore_msg.mc b/src/AspNetCoreModuleV2/CommonLib/aspnetcore_msg.mc index 477c1a0d0a..c71cbfeee2 100644 --- a/src/AspNetCoreModuleV2/CommonLib/aspnetcore_msg.mc +++ b/src/AspNetCoreModuleV2/CommonLib/aspnetcore_msg.mc @@ -237,6 +237,13 @@ Language=English %1 . +Messageid=1035 +SymbolicName=ASPNETCORE_EVENT_INPROCESS_THREAD_EXIT_STDOUT +Language=English +%1 +. + + ; ;#endif // _ASPNETCORE_MODULE_MSG_H_ ; diff --git a/src/AspNetCoreModuleV2/InProcessRequestHandler/inprocessapplication.cpp b/src/AspNetCoreModuleV2/InProcessRequestHandler/inprocessapplication.cpp index 756d78954c..2cbcc4d6f3 100644 --- a/src/AspNetCoreModuleV2/InProcessRequestHandler/inprocessapplication.cpp +++ b/src/AspNetCoreModuleV2/InProcessRequestHandler/inprocessapplication.cpp @@ -7,10 +7,10 @@ #include "requesthandler_config.h" #include "environmentvariablehelpers.h" #include "utility.h" -#include "EventLog.h" #include "SRWExclusiveLock.h" #include "exceptions.h" #include "LoggingHelpers.h" +#include "resources.h" const LPCSTR IN_PROCESS_APPLICATION::s_exeLocationParameterName = "InProcessExeLocation"; @@ -220,7 +220,6 @@ IN_PROCESS_APPLICATION::SetCallbackHandles( m_ShutdownHandlerContext = pvShutdownHandlerContext; m_AsyncCompletionHandler = async_completion_handler; - m_pLoggerProvider->NotifyStartupComplete(); // Can't check the std err handle as it isn't a critical error // Initialization complete UTILITY::LogEventF(g_hEventLog, @@ -498,11 +497,10 @@ Finished: m_status = APPLICATION_STATUS::SHUTDOWN; m_fShutdownCalledFromManaged = TRUE; FreeLibrary(hModule); + m_pLoggerProvider->Stop(); if (!m_fShutdownCalledFromNative) { - m_pLoggerProvider->NotifyStartupComplete(); - LogErrorsOnMainExit(hr); if (m_fInitialized) { @@ -533,7 +531,7 @@ IN_PROCESS_APPLICATION::LogErrorsOnMainExit( if (SUCCEEDED(struStdMsg.CopyA(straStdErrOutput.QueryStr()))) { UTILITY::LogEventF(g_hEventLog, EVENTLOG_ERROR_TYPE, - ASPNETCORE_EVENT_INPROCESS_THREAD_EXIT, + ASPNETCORE_EVENT_INPROCESS_THREAD_EXIT_STDOUT, ASPNETCORE_EVENT_INPROCESS_THREAD_EXIT_STDOUT_MSG, m_pConfig->QueryApplicationPath()->QueryStr(), m_pConfig->QueryApplicationPhysicalPath()->QueryStr(), diff --git a/src/AspNetCoreModuleV2/InProcessRequestHandler/managedexports.cpp b/src/AspNetCoreModuleV2/InProcessRequestHandler/managedexports.cpp index 6e03ebd859..af0035be11 100644 --- a/src/AspNetCoreModuleV2/InProcessRequestHandler/managedexports.cpp +++ b/src/AspNetCoreModuleV2/InProcessRequestHandler/managedexports.cpp @@ -18,8 +18,7 @@ register_callbacks( _In_ PFN_SHUTDOWN_HANDLER shutdown_handler, _In_ PFN_ASYNC_COMPLETION_HANDLER async_completion_handler, _In_ VOID* pvRequstHandlerContext, - _In_ VOID* pvShutdownHandlerContext, - _Out_ BOOL* pfResetStandardStreams + _In_ VOID* pvShutdownHandlerContext ) { if (pInProcessApplication == NULL) @@ -34,7 +33,6 @@ register_callbacks( pvRequstHandlerContext, pvShutdownHandlerContext ); - *pfResetStandardStreams = !pInProcessApplication->QueryConfig()->QueryStdoutLogEnabled(); return S_OK; } diff --git a/src/AspNetCoreModuleV2/RequestHandlerLib/FileOutputManager.cpp b/src/AspNetCoreModuleV2/RequestHandlerLib/FileOutputManager.cpp index 358d0f79cd..c5734eeb46 100644 --- a/src/AspNetCoreModuleV2/RequestHandlerLib/FileOutputManager.cpp +++ b/src/AspNetCoreModuleV2/RequestHandlerLib/FileOutputManager.cpp @@ -7,48 +7,20 @@ #include "utility.h" #include "exceptions.h" #include "debugutil.h" +#include "SRWExclusiveLock.h" FileOutputManager::FileOutputManager() : m_hLogFileHandle(INVALID_HANDLE_VALUE), m_fdPreviousStdOut(-1), - m_fdPreviousStdErr(-1) + m_fdPreviousStdErr(-1), + m_disposed(false) { + InitializeSRWLock(&m_srwLock); } FileOutputManager::~FileOutputManager() { - 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); - // 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); - } + Stop(); } HRESULT @@ -100,8 +72,6 @@ bool FileOutputManager::GetStdOutContent(STRA* struStdOutput) } } - LOG_INFOF("First 4KB captured by stdout: %s", pzFileContents); - return fLogged; } @@ -174,3 +144,52 @@ FileOutputManager::Start() 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; +} diff --git a/src/AspNetCoreModuleV2/RequestHandlerLib/FileOutputManager.h b/src/AspNetCoreModuleV2/RequestHandlerLib/FileOutputManager.h index f9a617ccf9..b1a43e6b0d 100644 --- a/src/AspNetCoreModuleV2/RequestHandlerLib/FileOutputManager.h +++ b/src/AspNetCoreModuleV2/RequestHandlerLib/FileOutputManager.h @@ -19,7 +19,7 @@ public: virtual bool GetStdOutContent(STRA* struStdOutput) override; virtual HRESULT Start() override; - virtual void NotifyStartupComplete() override {}; + virtual HRESULT Stop() override; private: HandleWrapper m_hLogFileHandle; @@ -29,5 +29,7 @@ private: STRU m_struLogFilePath; int m_fdPreviousStdOut; int m_fdPreviousStdErr; + BOOL m_disposed; + SRWLOCK m_srwLock; }; diff --git a/src/AspNetCoreModuleV2/RequestHandlerLib/IOutputManager.h b/src/AspNetCoreModuleV2/RequestHandlerLib/IOutputManager.h index 386e6d1a4f..b7e04df059 100644 --- a/src/AspNetCoreModuleV2/RequestHandlerLib/IOutputManager.h +++ b/src/AspNetCoreModuleV2/RequestHandlerLib/IOutputManager.h @@ -14,12 +14,12 @@ public: virtual ~IOutputManager() {}; - virtual - void - NotifyStartupComplete() = 0; - virtual bool GetStdOutContent(STRA* struStdOutput) = 0; + + virtual + HRESULT + Stop() = 0; }; diff --git a/src/AspNetCoreModuleV2/RequestHandlerLib/NullOutputManager.h b/src/AspNetCoreModuleV2/RequestHandlerLib/NullOutputManager.h index e2cec68179..389f967b69 100644 --- a/src/AspNetCoreModuleV2/RequestHandlerLib/NullOutputManager.h +++ b/src/AspNetCoreModuleV2/RequestHandlerLib/NullOutputManager.h @@ -15,12 +15,12 @@ public: HRESULT Start() { - // The process has console, e.g., IIS Express scenario return S_OK; } - void NotifyStartupComplete() + HRESULT Stop() { + return S_OK; } bool GetStdOutContent(STRA*) diff --git a/src/AspNetCoreModuleV2/RequestHandlerLib/PipeOutputManager.cpp b/src/AspNetCoreModuleV2/RequestHandlerLib/PipeOutputManager.cpp index ade993f37b..6fdcdb078b 100644 --- a/src/AspNetCoreModuleV2/RequestHandlerLib/PipeOutputManager.cpp +++ b/src/AspNetCoreModuleV2/RequestHandlerLib/PipeOutputManager.cpp @@ -14,7 +14,7 @@ PipeOutputManager::PipeOutputManager() : m_hErrReadPipe(INVALID_HANDLE_VALUE), m_hErrWritePipe(INVALID_HANDLE_VALUE), m_hErrThread(NULL), - m_fDisposed(FALSE), + m_disposed(FALSE), m_fdPreviousStdOut(-1), m_fdPreviousStdErr(-1) { @@ -23,26 +23,61 @@ PipeOutputManager::PipeOutputManager() : PipeOutputManager::~PipeOutputManager() { - StopOutputRedirection(); + Stop(); } -VOID -PipeOutputManager::StopOutputRedirection() +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; +} + +HRESULT PipeOutputManager::Stop() { DWORD dwThreadStatus = 0; STRA straStdOutput; - if (m_fDisposed) + if (m_disposed) { - return; + return S_OK; } SRWExclusiveLock lock(m_srwLock); - if (m_fDisposed) + if (m_disposed) { - return; + return S_OK; } - m_fDisposed = true; + m_disposed = true; fflush(stdout); fflush(stderr); @@ -115,40 +150,6 @@ PipeOutputManager::StopOutputRedirection() // Need to flush contents for the new stdout and stderr _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; } @@ -163,16 +164,17 @@ PipeOutputManager::ReadStdErrHandle( pLoggingProvider->ReadStdErrHandleInternal(); } -bool PipeOutputManager::GetStdOutContent(STRA* struStdOutput) +bool PipeOutputManager::GetStdOutContent(STRA* straStdOutput) { bool fLogged = false; if (m_dwStdErrReadTotal > 0) { - if (SUCCEEDED(struStdOutput->Copy(m_pzFileContents, m_dwStdErrReadTotal))) + if (SUCCEEDED(straStdOutput->Copy(m_pzFileContents, m_dwStdErrReadTotal))) { fLogged = TRUE; } } + return fLogged; } @@ -194,13 +196,19 @@ PipeOutputManager::ReadStdErrHandleInternal( } 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(); -} diff --git a/src/AspNetCoreModuleV2/RequestHandlerLib/PipeOutputManager.h b/src/AspNetCoreModuleV2/RequestHandlerLib/PipeOutputManager.h index 9a9b306700..3a15c2e68e 100644 --- a/src/AspNetCoreModuleV2/RequestHandlerLib/PipeOutputManager.h +++ b/src/AspNetCoreModuleV2/RequestHandlerLib/PipeOutputManager.h @@ -13,30 +13,26 @@ public: PipeOutputManager(); ~PipeOutputManager(); - // Inherited via ILoggerProvider virtual HRESULT Start() override; - virtual void NotifyStartupComplete() override; - - // Inherited via IOutputManager + virtual HRESULT Stop() override; virtual bool GetStdOutContent(STRA* struStdOutput) override; + // Thread functions VOID ReadStdErrHandleInternal(VOID); static VOID ReadStdErrHandle(LPVOID pContext); private: - VOID StopOutputRedirection(); - HANDLE m_hErrReadPipe; HANDLE m_hErrWritePipe; STRU m_struLogFilePath; HANDLE m_hErrThread; CHAR m_pzFileContents[MAX_PIPE_READ_SIZE] = { 0 }; DWORD m_dwStdErrReadTotal; - BOOL m_fDisposed; SRWLOCK m_srwLock; int m_fdPreviousStdOut; int m_fdPreviousStdErr; + BOOL m_disposed; }; diff --git a/src/Microsoft.AspNetCore.Server.IIS/Core/IISNativeApplication.cs b/src/Microsoft.AspNetCore.Server.IIS/Core/IISNativeApplication.cs index 44f9b40bef..d8544239c5 100644 --- a/src/Microsoft.AspNetCore.Server.IIS/Core/IISNativeApplication.cs +++ b/src/Microsoft.AspNetCore.Server.IIS/Core/IISNativeApplication.cs @@ -38,33 +38,7 @@ namespace Microsoft.AspNetCore.Server.IIS.Core shutdownHandler, onAsyncCompletion, requestContext, - 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 }; + shutdownContext); } public void Dispose() diff --git a/src/Microsoft.AspNetCore.Server.IIS/NativeMethods.cs b/src/Microsoft.AspNetCore.Server.IIS/NativeMethods.cs index 8a6da21e8a..e8aa17a430 100644 --- a/src/Microsoft.AspNetCore.Server.IIS/NativeMethods.cs +++ b/src/Microsoft.AspNetCore.Server.IIS/NativeMethods.cs @@ -59,8 +59,7 @@ namespace Microsoft.AspNetCore.Server.IIS PFN_SHUTDOWN_HANDLER shutdownCallback, PFN_ASYNC_COMPLETION asyncCallback, IntPtr pvRequestContext, - IntPtr pvShutdownContext, - out bool resetStandardStreams); + IntPtr pvShutdownContext); [DllImport(AspNetCoreModuleDll)] 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_ASYNC_COMPLETION asyncCallback, IntPtr pvRequestContext, - IntPtr pvShutdownContext, - out bool resetStandardStreams) + IntPtr pvShutdownContext) { - 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) diff --git a/test/Common.FunctionalTests/Inprocess/LoggingTests.cs b/test/Common.FunctionalTests/Inprocess/LoggingTests.cs index eb3294a537..15e9c8c1d9 100644 --- a/test/Common.FunctionalTests/Inprocess/LoggingTests.cs +++ b/test/Common.FunctionalTests/Inprocess/LoggingTests.cs @@ -108,6 +108,7 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests public async Task CheckStdoutLoggingToPipe_DoesNotCrashProcess(string path) { var deploymentParameters = Helpers.GetBaseDeploymentParameters(publish: true); + deploymentParameters.GracefulShutdown = true; var deploymentResult = await DeployAsync(deploymentParameters); await Helpers.AssertStarts(deploymentResult, path); @@ -126,6 +127,8 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests public async Task CheckStdoutLoggingToPipeWithFirstWrite(string path) { var deploymentParameters = Helpers.GetBaseDeploymentParameters(publish: true); + deploymentParameters.GracefulShutdown = true; + var firstWriteString = path + path; deploymentParameters.WebConfigBasedEnvironmentVariables["ASPNETCORE_INPROCESS_INITIAL_WRITE"] = firstWriteString; diff --git a/test/CommonLibTests/PipeOutputManagerTests.cpp b/test/CommonLibTests/PipeOutputManagerTests.cpp index 67ce9f2f04..6cc09e7678 100644 --- a/test/CommonLibTests/PipeOutputManagerTests.cpp +++ b/test/CommonLibTests/PipeOutputManagerTests.cpp @@ -29,9 +29,6 @@ namespace PipeOutputManagerTests PipeOutputManager* pManager = new PipeOutputManager(); ASSERT_EQ(S_OK, pManager->Start()); - - pManager->NotifyStartupComplete(); - } TEST(PipeManagerOutputTest, SetInvalidHandlesForErrAndOut) @@ -47,8 +44,6 @@ namespace PipeOutputManagerTests PipeOutputManager* pManager = new PipeOutputManager(); ASSERT_EQ(S_OK, pManager->Start()); - pManager->NotifyStartupComplete(); - _dup2(m_fdPreviousStdOut, _fileno(stdout)); _dup2(m_fdPreviousStdErr, _fileno(stderr)); diff --git a/test/IIS.FunctionalTests/IIS.FunctionalTests.csproj b/test/IIS.FunctionalTests/IIS.FunctionalTests.csproj index 319a3726b1..73c2d11f70 100644 --- a/test/IIS.FunctionalTests/IIS.FunctionalTests.csproj +++ b/test/IIS.FunctionalTests/IIS.FunctionalTests.csproj @@ -30,7 +30,6 @@ - From 7d641f87969be1ce160a8f3f504e5a1d2fb512cb Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Mon, 30 Jul 2018 08:27:06 -0700 Subject: [PATCH 4/5] Skip VSTS attribute (#1115) --- .vsts-pipelines/templates/build-steps.yml | 2 ++ .../Common.FunctionalTests/SkipVSTSAttribute.cs | 17 +++++++++++++++++ .../Utilities/SkipIISAttribute.cs | 0 .../OutOfProcess/HttpsTest.cs | 1 + 4 files changed, 20 insertions(+) create mode 100644 test/Common.FunctionalTests/SkipVSTSAttribute.cs delete mode 100644 test/Common.FunctionalTests/Utilities/SkipIISAttribute.cs diff --git a/.vsts-pipelines/templates/build-steps.yml b/.vsts-pipelines/templates/build-steps.yml index 40843183ea..33d1e65180 100644 --- a/.vsts-pipelines/templates/build-steps.yml +++ b/.vsts-pipelines/templates/build-steps.yml @@ -3,6 +3,8 @@ phases: parameters: agentOs: Windows beforeBuild: + - powershell: "git submodule update --init" + displayName: Update submodules - powershell: "& ./tools/update_schema.ps1" displayName: Update ANCM schema - powershell: Restart-Service w3svc diff --git a/test/Common.FunctionalTests/SkipVSTSAttribute.cs b/test/Common.FunctionalTests/SkipVSTSAttribute.cs new file mode 100644 index 0000000000..8e88fc8c26 --- /dev/null +++ b/test/Common.FunctionalTests/SkipVSTSAttribute.cs @@ -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"; + } +} diff --git a/test/Common.FunctionalTests/Utilities/SkipIISAttribute.cs b/test/Common.FunctionalTests/Utilities/SkipIISAttribute.cs deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/test/IISExpress.FunctionalTests/OutOfProcess/HttpsTest.cs b/test/IISExpress.FunctionalTests/OutOfProcess/HttpsTest.cs index ff9996c851..4f0c93b400 100644 --- a/test/IISExpress.FunctionalTests/OutOfProcess/HttpsTest.cs +++ b/test/IISExpress.FunctionalTests/OutOfProcess/HttpsTest.cs @@ -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 // creating self-signed certificates and registering SSL bindings with HTTP.sys // Test specific to IISExpress + [SkipInVSTS] public class HttpsTest : IISFunctionalTestBase { public HttpsTest(ITestOutputHelper output) : base(output) From 7a4a945fd65e442265c44150800b5f2e3e8349c8 Mon Sep 17 00:00:00 2001 From: Justin Kotalik Date: Mon, 30 Jul 2018 12:58:48 -0700 Subject: [PATCH 5/5] Stop site and app pool before restoring config (#1112) --- .../IISApplication.cs | 46 +++++++++++++++---- .../IISDeployer.cs | 6 ++- 2 files changed, 42 insertions(+), 10 deletions(-) diff --git a/src/Microsoft.AspNetCore.Server.IntegrationTesting.IIS/IISApplication.cs b/src/Microsoft.AspNetCore.Server.IntegrationTesting.IIS/IISApplication.cs index bf0c338efc..ce1f3e426e 100644 --- a/src/Microsoft.AspNetCore.Server.IntegrationTesting.IIS/IISApplication.cs +++ b/src/Microsoft.AspNetCore.Server.IntegrationTesting.IIS/IISApplication.cs @@ -65,7 +65,7 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting } AddTemporaryAppHostConfig(); - var apppool = ConfigureAppPool(contentRoot); + ConfigureAppPool(contentRoot); ConfigureSite(contentRoot, port); @@ -73,11 +73,11 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting _serverManager.CommitChanges(); - await WaitUntilSiteStarted(apppool); + await WaitUntilSiteStarted(); } } - private async Task WaitUntilSiteStarted(ApplicationPool appPool) + private async Task WaitUntilSiteStarted() { var sw = Stopwatch.StartNew(); @@ -85,12 +85,19 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting { 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) { - _logger.LogInformation($"Site {WebSiteName} has started."); - return; + var workerProcess = appPool.WorkerProcesses.SingleOrDefault(); + if (workerProcess != null) + { + HostProcess = Process.GetProcessById(workerProcess.ProcessId); + _logger.LogInformation($"Site {WebSiteName} has started."); + return; + } } else if (site.State != ObjectState.Starting) { @@ -122,11 +129,15 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting return; } - RestoreAppHostConfig(); + StopSite(); + + StopAppPool(); _serverManager.CommitChanges(); await WaitUntilSiteStopped(); + + RestoreAppHostConfig(); } private async Task WaitUntilSiteStopped() @@ -145,8 +156,11 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting { if (site.State == ObjectState.Stopped) { - _logger.LogInformation($"Site {WebSiteName} has stopped successfully."); - return; + if (HostProcess.HasExited) + { + _logger.LogInformation($"Site {WebSiteName} has stopped successfully."); + return; + } } } catch (COMException) @@ -275,6 +289,20 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting 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) { var ancmFile = GetAncmLocation(dllRoot); diff --git a/src/Microsoft.AspNetCore.Server.IntegrationTesting.IIS/IISDeployer.cs b/src/Microsoft.AspNetCore.Server.IntegrationTesting.IIS/IISDeployer.cs index 18b8e5d2ea..ffbc8ba034 100644 --- a/src/Microsoft.AspNetCore.Server.IntegrationTesting.IIS/IISDeployer.cs +++ b/src/Microsoft.AspNetCore.Server.IntegrationTesting.IIS/IISDeployer.cs @@ -106,7 +106,11 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting.IIS 5, 200); - Logger.LogInformation($"Found debug log file: {file}"); + if (arr.Length == 0) + { + Logger.LogWarning($"{file} is empty."); + } + foreach (var line in arr) { Logger.LogInformation(line);