diff --git a/build/dependencies.props b/build/dependencies.props
index d8c5e54b45..1027e444c9 100644
--- a/build/dependencies.props
+++ b/build/dependencies.props
@@ -52,6 +52,6 @@
2.3.1
2.4.0
-
+
diff --git a/src/AspNetCoreModuleV1/AspNetCore/Inc/resource.h b/src/AspNetCoreModuleV1/AspNetCore/Inc/resource.h
index 899e9a5c93..6330be8879 100644
--- a/src/AspNetCoreModuleV1/AspNetCore/Inc/resource.h
+++ b/src/AspNetCoreModuleV1/AspNetCore/Inc/resource.h
@@ -11,7 +11,7 @@
#define ASPNETCORE_EVENT_RAPID_FAIL_COUNT_EXCEEDED_MSG L"Maximum rapid fail count per minute of '%d' exceeded."
#define ASPNETCORE_EVENT_PROCESS_START_INTERNAL_ERROR_MSG L"Application '%s' failed to parse processPath and arguments due to internal error, ErrorCode = '0x%x'."
#define ASPNETCORE_EVENT_PROCESS_START_POSTCREATE_ERROR_MSG L"Application '%s' with physical root '%s' created process with commandline '%s'but failed to get its status, ErrorCode = '0x%x'."
-#define ASPNETCORE_EVENT_PROCESS_START_ERROR_MSG L"Application '%s' with physical root '%s' failed to start process with commandline '%s', ErrorCode = '0x%x : %x."
+#define ASPNETCORE_EVENT_PROCESS_START_ERROR_MSG L"Application '%s' with physical root '%s' failed to start process with commandline '%s', ErrorCode = '0x%x' : %x."
#define ASPNETCORE_EVENT_PROCESS_START_WRONGPORT_ERROR_MSG L"Application '%s' with physical root '%s' created process with commandline '%s' but failed to listen on the given port '%d'"
#define ASPNETCORE_EVENT_PROCESS_START_NOTREADY_ERROR_MSG L"Application '%s' with physical root '%s' created process with commandline '%s' but either crashed or did not reponse or did not listen on the given port '%d', ErrorCode = '0x%x'"
#define ASPNETCORE_EVENT_INVALID_STDOUT_LOG_FILE_MSG L"Warning: Could not create stdoutLogFile %s, ErrorCode = %d."
diff --git a/src/AspNetCoreModuleV1/AspNetCore/aspnetcore_msg.mc b/src/AspNetCoreModuleV1/AspNetCore/aspnetcore_msg.mc
index 0bbc4fa1c2..73eb713f1c 100644
--- a/src/AspNetCoreModuleV1/AspNetCore/aspnetcore_msg.mc
+++ b/src/AspNetCoreModuleV1/AspNetCore/aspnetcore_msg.mc
@@ -1,6 +1,7 @@
;/*++
;
-;Copyright (c) 2014 Microsoft Corporation
+; Copyright (c) .NET Foundation. All rights reserved.
+; Licensed under the MIT License. See License.txt in the project root for license information.
;
;Module Name:
;
diff --git a/src/AspNetCoreModuleV1/AspNetCore/aspnetcoremodule.rc b/src/AspNetCoreModuleV1/AspNetCore/aspnetcoremodule.rc
index 6d771d50bd..7790f5067f 100644
--- a/src/AspNetCoreModuleV1/AspNetCore/aspnetcoremodule.rc
+++ b/src/AspNetCoreModuleV1/AspNetCore/aspnetcoremodule.rc
@@ -3,6 +3,7 @@
#include
#include "version.h"
#include "resource.h"
+#include "Aspnetcore_msg.rc"
/////////////////////////////////////////////////////////////////////////////
// English (United States) resources
@@ -75,10 +76,10 @@ BEGIN
BEGIN
BLOCK "040904b0"
BEGIN
- VALUE "CompanyName", "Microsoft"
+ VALUE "CompanyName", "Microsoft Corporation"
VALUE "FileDescription", FileDescription
VALUE "FileVersion", FileVersionStr
- VALUE "InternalName", "aspnetcore.dll"
+ VALUE "InternalName", "aspnetcore"
VALUE "LegalCopyright", "Copyright (C) Microsoft Corporation"
VALUE "OriginalFilename", "aspnetcore.dll"
VALUE "ProductName", "ASP.NET Core Module"
diff --git a/src/AspNetCoreModuleV1/AspNetCore/src/serverprocess.cxx b/src/AspNetCoreModuleV1/AspNetCore/src/serverprocess.cxx
index 76da27a99b..b3fd02432a 100644
--- a/src/AspNetCoreModuleV1/AspNetCore/src/serverprocess.cxx
+++ b/src/AspNetCoreModuleV1/AspNetCore/src/serverprocess.cxx
@@ -132,7 +132,7 @@ SERVER_PROCESS::SetupListenPort(
pEnvironmentVarTable->FindKey(ASPNETCORE_PORT_ENV_STR, &pEntry);
if (pEntry != NULL)
{
- if (pEntry->QueryValue() != NULL || pEntry->QueryValue()[0] != L'\0')
+ if (pEntry->QueryValue() != NULL && pEntry->QueryValue()[0] != L'\0')
{
m_dwPort = (DWORD)_wtoi(pEntry->QueryValue());
if(m_dwPort >MAX_PORT || m_dwPort < MIN_PORT)
@@ -150,6 +150,8 @@ SERVER_PROCESS::SetupListenPort(
// user set the env variable but did not give value, let's set it up
//
pEnvironmentVarTable->DeleteKey(ASPNETCORE_PORT_ENV_STR);
+ pEntry->Dereference();
+ pEntry = NULL;
}
}
@@ -1068,8 +1070,8 @@ Finished:
{
if (!fDonePrepareCommandLine)
strEventMsg.SafeSnwprintf(
- m_struAppFullPath.QueryStr(),
ASPNETCORE_EVENT_PROCESS_START_INTERNAL_ERROR_MSG,
+ m_struAppFullPath.QueryStr(),
hr);
else
strEventMsg.SafeSnwprintf(
diff --git a/src/AspNetCoreModuleV2/AspNetCore/HandlerResolver.cpp b/src/AspNetCoreModuleV2/AspNetCore/HandlerResolver.cpp
index 6c78cc16a6..49d1a29093 100644
--- a/src/AspNetCoreModuleV2/AspNetCore/HandlerResolver.cpp
+++ b/src/AspNetCoreModuleV2/AspNetCore/HandlerResolver.cpp
@@ -10,6 +10,8 @@
#include "GlobalVersionUtility.h"
#include "HandleWrapper.h"
#include "file_utility.h"
+#include "LoggingHelpers.h"
+#include "resources.h"
const PCWSTR HandlerResolver::s_pwzAspnetcoreInProcessRequestHandlerName = L"aspnetcorev2_inprocess.dll";
const PCWSTR HandlerResolver::s_pwzAspnetcoreOutOfProcessRequestHandlerName = L"aspnetcorev2_outofprocess.dll";
@@ -46,6 +48,7 @@ HandlerResolver::LoadRequestHandlerAssembly(IHttpApplication &pApplication, STRU
if (pConfiguration->QueryHostingModel() == APP_HOSTING_MODEL::HOSTING_IN_PROCESS)
{
std::unique_ptr options;
+ std::unique_ptr outputManager;
RETURN_IF_FAILED(HOSTFXR_OPTIONS::Create(
NULL,
@@ -56,14 +59,35 @@ HandlerResolver::LoadRequestHandlerAssembly(IHttpApplication &pApplication, STRU
RETURN_IF_FAILED(location.Copy(options->GetExeLocation()));
- if (FAILED_LOG(hr = FindNativeAssemblyFromHostfxr(options.get(), pstrHandlerDllName, &struFileName)))
- {
- EventLog::Error(
- ASPNETCORE_EVENT_INPROCESS_RH_MISSING,
- ASPNETCORE_EVENT_INPROCESS_RH_MISSING_MSG,
- struFileName.IsEmpty() ? s_pwzAspnetcoreInProcessRequestHandlerName : struFileName.QueryStr());
+ RETURN_IF_FAILED(LoggingHelpers::CreateLoggingProvider(
+ pConfiguration->QueryStdoutLogEnabled(),
+ !m_pServer.IsCommandLineLaunch(),
+ pConfiguration->QueryStdoutLogFile()->QueryStr(),
+ pApplication.GetApplicationPhysicalPath(),
+ outputManager));
+
+ outputManager->Start();
+
+ hr = FindNativeAssemblyFromHostfxr(options.get(), pstrHandlerDllName, &struFileName);
+ outputManager->Stop();
+
+ if (FAILED(hr) && m_hHostFxrDll != NULL)
+ {
+ STRA content;
+ STRU struStdMsg;
+
+ outputManager->GetStdOutContent(&content);
+ if (content.QueryCCH() > 0)
+ {
+ struStdMsg.CopyA(content.QueryStr());
+ }
+
+ EventLog::Error(
+ ASPNETCORE_EVENT_GENERAL_ERROR,
+ ASPNETCORE_EVENT_INPROCESS_RH_ERROR_MSG,
+ struFileName.IsEmpty() ? s_pwzAspnetcoreInProcessRequestHandlerName : struFileName.QueryStr(),
+ struStdMsg.QueryStr());
- return hr;
}
}
else
@@ -188,12 +212,23 @@ HandlerResolver::FindNativeAssemblyFromHostfxr(
BOOL fFound = FALSE;
DWORD dwBufferSize = 1024 * 10;
DWORD dwRequiredBufferSize = 0;
+ STRA output;
+
DBG_ASSERT(struFilename != NULL);
RETURN_LAST_ERROR_IF_NULL(m_hHostFxrDll = LoadLibraryW(hostfxrOptions->GetHostFxrLocation()));
auto pFnHostFxrSearchDirectories = reinterpret_cast(GetProcAddress(m_hHostFxrDll, "hostfxr_get_native_search_directories"));
+ if (pFnHostFxrSearchDirectories == nullptr)
+ {
+ EventLog::Error(
+ ASPNETCORE_EVENT_GENERAL_ERROR,
+ ASPNETCORE_EVENT_HOSTFXR_DLL_INVALID_VERSION_MSG,
+ hostfxrOptions->GetHostFxrLocation()
+ );
+ RETURN_IF_FAILED(E_FAIL);
+ }
RETURN_LAST_ERROR_IF_NULL(pFnHostFxrSearchDirectories);
RETURN_IF_FAILED(struNativeSearchPaths.Resize(dwBufferSize));
diff --git a/src/AspNetCoreModuleV2/AspNetCore/aspnetcore_shim_config.cpp b/src/AspNetCoreModuleV2/AspNetCore/aspnetcore_shim_config.cpp
index 10adc6e2b4..bf62cd9e87 100644
--- a/src/AspNetCoreModuleV2/AspNetCore/aspnetcore_shim_config.cpp
+++ b/src/AspNetCoreModuleV2/AspNetCore/aspnetcore_shim_config.cpp
@@ -29,7 +29,7 @@ ASPNETCORE_SHIM_CONFIG::Populate(
CS_ASPNETCORE_PROCESS_EXE_PATH,
&m_struProcessPath));
- // Swallow this error for backward compatability
+ // Swallow this error for backward compatibility
// Use default behavior for empty string
GetElementStringProperty(pAspNetCoreElement,
CS_ASPNETCORE_HOSTING_MODEL,
@@ -50,7 +50,7 @@ ASPNETCORE_SHIM_CONFIG::Populate(
ASPNETCORE_EVENT_UNKNOWN_HOSTING_MODEL_ERROR,
ASPNETCORE_EVENT_UNKNOWN_HOSTING_MODEL_ERROR_MSG,
strHostingModel.QueryStr());
- RETURN_IF_FAILED(HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED));
+ RETURN_HR(HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED));
}
RETURN_IF_FAILED(GetElementStringProperty(pAspNetCoreElement,
@@ -62,5 +62,13 @@ ASPNETCORE_SHIM_CONFIG::Populate(
RETURN_IF_FAILED(ConfigUtility::FindHandlerVersion(pAspNetCoreElement, m_struHandlerVersion));
}
+
+ RETURN_IF_FAILED(GetElementBoolProperty(pAspNetCoreElement,
+ CS_ASPNETCORE_STDOUT_LOG_ENABLED,
+ &m_fStdoutLogEnabled));
+ RETURN_IF_FAILED(GetElementStringProperty(pAspNetCoreElement,
+ CS_ASPNETCORE_STDOUT_LOG_FILE,
+ &m_struStdoutLogFile));
+
return S_OK;
}
diff --git a/src/AspNetCoreModuleV2/AspNetCore/aspnetcore_shim_config.h b/src/AspNetCoreModuleV2/AspNetCore/aspnetcore_shim_config.h
index 1ae97f79af..e80071b1c9 100644
--- a/src/AspNetCoreModuleV2/AspNetCore/aspnetcore_shim_config.h
+++ b/src/AspNetCoreModuleV2/AspNetCore/aspnetcore_shim_config.h
@@ -12,6 +12,8 @@
#define CS_ASPNETCORE_PROCESS_EXE_PATH L"processPath"
#define CS_ASPNETCORE_PROCESS_ARGUMENTS L"arguments"
#define CS_ASPNETCORE_HOSTING_MODEL L"hostingModel"
+#define CS_ASPNETCORE_STDOUT_LOG_ENABLED L"stdoutLogEnabled"
+#define CS_ASPNETCORE_STDOUT_LOG_FILE L"stdoutLogFile"
enum APP_HOSTING_MODEL
{
@@ -56,6 +58,18 @@ public:
return &m_struHandlerVersion;
}
+ BOOL
+ QueryStdoutLogEnabled()
+ {
+ return m_fStdoutLogEnabled;
+ }
+
+ STRU*
+ QueryStdoutLogFile()
+ {
+ return &m_struStdoutLogFile;
+ }
+
ASPNETCORE_SHIM_CONFIG() :
m_hostingModel(HOSTING_UNKNOWN)
{
@@ -67,5 +81,6 @@ private:
STRU m_struProcessPath;
APP_HOSTING_MODEL m_hostingModel;
STRU m_struHandlerVersion;
+ BOOL m_fStdoutLogEnabled;
+ STRU m_struStdoutLogFile;
};
-
diff --git a/src/AspNetCoreModuleV2/CommonLib/CommonLib.vcxproj b/src/AspNetCoreModuleV2/CommonLib/CommonLib.vcxproj
index 12e6ff1691..47a5373ee1 100644
--- a/src/AspNetCoreModuleV2/CommonLib/CommonLib.vcxproj
+++ b/src/AspNetCoreModuleV2/CommonLib/CommonLib.vcxproj
@@ -200,6 +200,7 @@
+
@@ -207,7 +208,12 @@
+
+
+
+
+
@@ -220,11 +226,15 @@
+
+
+
+
diff --git a/src/AspNetCoreModuleV2/CommonLib/EventLog.cpp b/src/AspNetCoreModuleV2/CommonLib/EventLog.cpp
index 7d10a8abf9..24992232de 100644
--- a/src/AspNetCoreModuleV2/CommonLib/EventLog.cpp
+++ b/src/AspNetCoreModuleV2/CommonLib/EventLog.cpp
@@ -27,7 +27,7 @@ EventLog::LogEvent(
);
}
- DebugPrintf(dwEventInfoType == EVENTLOG_ERROR_TYPE ? ASPNETCORE_DEBUG_FLAG_ERROR : ASPNETCORE_DEBUG_FLAG_INFO, "Event Log: %S", pstrMsg);
+ DebugPrintf(dwEventInfoType == EVENTLOG_ERROR_TYPE ? ASPNETCORE_DEBUG_FLAG_ERROR : ASPNETCORE_DEBUG_FLAG_INFO, "Event Log: %S \r\nEnd Event Log Message.", pstrMsg);
}
VOID
diff --git a/src/AspNetCoreModuleV2/CommonLib/FileOutputManager.cpp b/src/AspNetCoreModuleV2/CommonLib/FileOutputManager.cpp
new file mode 100644
index 0000000000..6e16ac2acd
--- /dev/null
+++ b/src/AspNetCoreModuleV2/CommonLib/FileOutputManager.cpp
@@ -0,0 +1,190 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for license information.
+
+#include "stdafx.h"
+#include "FileOutputManager.h"
+#include "sttimer.h"
+#include "exceptions.h"
+#include "debugutil.h"
+#include "SRWExclusiveLock.h"
+#include "file_utility.h"
+#include "StdWrapper.h"
+
+extern HINSTANCE g_hModule;
+
+FileOutputManager::FileOutputManager() :
+ FileOutputManager(/* fEnableNativeLogging */ true) { }
+
+FileOutputManager::FileOutputManager(bool fEnableNativeLogging) :
+ m_hLogFileHandle(INVALID_HANDLE_VALUE),
+ m_disposed(false),
+ stdoutWrapper(nullptr),
+ stderrWrapper(nullptr),
+ m_fEnableNativeRedirection(fEnableNativeLogging)
+{
+ InitializeSRWLock(&m_srwLock);
+}
+
+FileOutputManager::~FileOutputManager()
+{
+ FileOutputManager::Stop();
+}
+
+HRESULT
+FileOutputManager::Initialize(PCWSTR pwzStdOutLogFileName, PCWSTR pwzApplicationPath)
+{
+ RETURN_IF_FAILED(m_wsApplicationPath.Copy(pwzApplicationPath));
+ RETURN_IF_FAILED(m_wsStdOutLogFileName.Copy(pwzStdOutLogFileName));
+
+ return S_OK;
+}
+
+// Start redirecting stdout and stderr into the file handle.
+// Uses sttimer to continuously flush output into the file.
+HRESULT
+FileOutputManager::Start()
+{
+ SYSTEMTIME systemTime;
+ SECURITY_ATTRIBUTES saAttr = { 0 };
+ STRU struPath;
+
+ // Concatenate the log file name and application path
+ RETURN_IF_FAILED(FILE_UTILITY::ConvertPathToFullPath(
+ m_wsStdOutLogFileName.QueryStr(),
+ m_wsApplicationPath.QueryStr(),
+ &struPath));
+
+ RETURN_IF_FAILED(FILE_UTILITY::EnsureDirectoryPathExist(struPath.QueryStr()));
+
+ // Get the module name and add it to the log file name
+ // as two log files will be created, one from the shim
+ // and one from the request handler.
+ WCHAR path[MAX_PATH];
+ RETURN_LAST_ERROR_IF(!GetModuleFileName(g_hModule, path, sizeof(path)));
+ std::filesystem::path fsPath(path);
+
+ // TODO fix string as it is incorrect
+ GetSystemTime(&systemTime);
+
+ RETURN_IF_FAILED(
+ m_struLogFilePath.SafeSnwprintf(L"%s_%d%02d%02d%02d%02d%02d_%d_%s.log",
+ struPath.QueryStr(),
+ systemTime.wYear,
+ systemTime.wMonth,
+ systemTime.wDay,
+ systemTime.wHour,
+ systemTime.wMinute,
+ systemTime.wSecond,
+ GetCurrentProcessId(),
+ fsPath.filename().stem().c_str()));
+
+ saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
+ saAttr.bInheritHandle = TRUE;
+ saAttr.lpSecurityDescriptor = NULL;
+
+ // Create the file with both READ and WRITE.
+ m_hLogFileHandle = CreateFileW(m_struLogFilePath.QueryStr(),
+ FILE_READ_DATA | FILE_WRITE_DATA,
+ FILE_SHARE_READ,
+ &saAttr,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ nullptr);
+
+ RETURN_LAST_ERROR_IF(m_hLogFileHandle == INVALID_HANDLE_VALUE);
+
+ stdoutWrapper = std::make_unique(stdout, STD_OUTPUT_HANDLE, m_hLogFileHandle, m_fEnableNativeRedirection);
+ stderrWrapper = std::make_unique(stderr, STD_ERROR_HANDLE, m_hLogFileHandle, m_fEnableNativeRedirection);
+
+ stdoutWrapper->StartRedirection();
+ stderrWrapper->StartRedirection();
+
+ return S_OK;
+}
+
+
+HRESULT
+FileOutputManager::Stop()
+{
+ STRA straStdOutput;
+ CHAR pzFileContents[MAX_FILE_READ_SIZE] = { 0 };
+ DWORD dwNumBytesRead;
+ LARGE_INTEGER li = { 0 };
+ DWORD dwFilePointer = 0;
+ HANDLE handle = NULL;
+ WIN32_FIND_DATA fileData;
+
+ if (m_disposed)
+ {
+ return S_OK;
+ }
+
+ SRWExclusiveLock lock(m_srwLock);
+
+ if (m_disposed)
+ {
+ return S_OK;
+ }
+
+ m_disposed = true;
+
+ if (m_hLogFileHandle == INVALID_HANDLE_VALUE)
+ {
+ return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
+ }
+
+ FlushFileBuffers(m_hLogFileHandle);
+
+ if (stdoutWrapper != nullptr)
+ {
+ RETURN_IF_FAILED(stdoutWrapper->StopRedirection());
+ }
+
+ if (stderrWrapper != nullptr)
+ {
+ RETURN_IF_FAILED(stderrWrapper->StopRedirection());
+ }
+
+ // 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()));
+ }
+
+ // Read the first 30Kb from the file and store it in a buffer.
+ // By doing this, we can close the handle to the file and be done with it.
+ RETURN_LAST_ERROR_IF(!GetFileSizeEx(m_hLogFileHandle, &li));
+
+ if (li.LowPart == 0 || li.HighPart > 0)
+ {
+ RETURN_IF_FAILED(HRESULT_FROM_WIN32(ERROR_FILE_INVALID));
+ }
+
+ dwFilePointer = SetFilePointer(m_hLogFileHandle, 0, NULL, FILE_BEGIN);
+
+ RETURN_LAST_ERROR_IF(dwFilePointer == INVALID_SET_FILE_POINTER);
+
+ RETURN_LAST_ERROR_IF(!ReadFile(m_hLogFileHandle, pzFileContents, MAX_FILE_READ_SIZE, &dwNumBytesRead, NULL));
+
+ m_straFileContent.Copy(pzFileContents, dwNumBytesRead);
+
+ // printf will fail in in full IIS
+ if (printf(m_straFileContent.QueryStr()) != -1)
+ {
+ // Need to flush contents for the new stdout and stderr
+ _flushall();
+ }
+
+ return S_OK;
+}
+
+bool FileOutputManager::GetStdOutContent(STRA* struStdOutput)
+{
+ struStdOutput->Copy(m_straFileContent);
+ return m_straFileContent.QueryCCH() > 0;
+}
diff --git a/src/AspNetCoreModuleV2/RequestHandlerLib/FileOutputManager.h b/src/AspNetCoreModuleV2/CommonLib/FileOutputManager.h
similarity index 70%
rename from src/AspNetCoreModuleV2/RequestHandlerLib/FileOutputManager.h
rename to src/AspNetCoreModuleV2/CommonLib/FileOutputManager.h
index b1a43e6b0d..94f6e19176 100644
--- a/src/AspNetCoreModuleV2/RequestHandlerLib/FileOutputManager.h
+++ b/src/AspNetCoreModuleV2/CommonLib/FileOutputManager.h
@@ -6,12 +6,17 @@
#include "sttimer.h"
#include "IOutputManager.h"
#include "HandleWrapper.h"
+#include "StdWrapper.h"
+#include "stringa.h"
+#include "stringu.h"
class FileOutputManager : public IOutputManager
{
#define FILE_FLUSH_TIMEOUT 3000
+ #define MAX_FILE_READ_SIZE 30000
public:
FileOutputManager();
+ FileOutputManager(bool fEnableNativeLogging);
~FileOutputManager();
HRESULT
@@ -27,9 +32,10 @@ private:
STRU m_wsStdOutLogFileName;
STRU m_wsApplicationPath;
STRU m_struLogFilePath;
- int m_fdPreviousStdOut;
- int m_fdPreviousStdErr;
+ STRA m_straFileContent;
BOOL m_disposed;
- SRWLOCK m_srwLock;
+ BOOL m_fEnableNativeRedirection;
+ SRWLOCK m_srwLock{};
+ std::unique_ptr stdoutWrapper;
+ std::unique_ptr stderrWrapper;
};
-
diff --git a/src/AspNetCoreModuleV2/CommonLib/HandleWrapper.h b/src/AspNetCoreModuleV2/CommonLib/HandleWrapper.h
index 6764f4c14d..d6b50f2381 100644
--- a/src/AspNetCoreModuleV2/CommonLib/HandleWrapper.h
+++ b/src/AspNetCoreModuleV2/CommonLib/HandleWrapper.h
@@ -4,6 +4,7 @@
#pragma once
#include
+#include
struct InvalidHandleTraits
{
diff --git a/src/AspNetCoreModuleV2/RequestHandlerLib/IOutputManager.h b/src/AspNetCoreModuleV2/CommonLib/IOutputManager.h
similarity index 94%
rename from src/AspNetCoreModuleV2/RequestHandlerLib/IOutputManager.h
rename to src/AspNetCoreModuleV2/CommonLib/IOutputManager.h
index b7e04df059..6b733dd0e6 100644
--- a/src/AspNetCoreModuleV2/RequestHandlerLib/IOutputManager.h
+++ b/src/AspNetCoreModuleV2/CommonLib/IOutputManager.h
@@ -1,9 +1,11 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
-#include "stdafx.h"
-
#pragma once
+
+#include "stdafx.h"
+#include "stringa.h"
+
class IOutputManager
{
public:
diff --git a/src/AspNetCoreModuleV2/RequestHandlerLib/LoggingHelpers.cpp b/src/AspNetCoreModuleV2/CommonLib/LoggingHelpers.cpp
similarity index 62%
rename from src/AspNetCoreModuleV2/RequestHandlerLib/LoggingHelpers.cpp
rename to src/AspNetCoreModuleV2/CommonLib/LoggingHelpers.cpp
index a133172db4..69de017e7f 100644
--- a/src/AspNetCoreModuleV2/RequestHandlerLib/LoggingHelpers.cpp
+++ b/src/AspNetCoreModuleV2/CommonLib/LoggingHelpers.cpp
@@ -7,14 +7,18 @@
#include "FileOutputManager.h"
#include "PipeOutputManager.h"
#include "NullOutputManager.h"
+#include "debugutil.h"
+#include
+#include
+#include "ntassert.h"
HRESULT
LoggingHelpers::CreateLoggingProvider(
bool fIsLoggingEnabled,
- bool fEnablePipe,
+ bool fEnableNativeLogging,
PCWSTR pwzStdOutFileName,
PCWSTR pwzApplicationPath,
- _Out_ IOutputManager** outputManager
+ std::unique_ptr& outputManager
)
{
HRESULT hr = S_OK;
@@ -25,17 +29,17 @@ LoggingHelpers::CreateLoggingProvider(
{
if (fIsLoggingEnabled)
{
- FileOutputManager* manager = new FileOutputManager;
+ auto manager = std::make_unique(fEnableNativeLogging);
hr = manager->Initialize(pwzStdOutFileName, pwzApplicationPath);
- *outputManager = manager;
+ outputManager = std::move(manager);
}
- else if (fEnablePipe)
+ else if (!GetConsoleWindow())
{
- *outputManager = new PipeOutputManager;
+ outputManager = std::make_unique(fEnableNativeLogging);
}
else
{
- *outputManager = new NullOutputManager;
+ outputManager = std::make_unique();
}
}
catch (std::bad_alloc&)
diff --git a/src/AspNetCoreModuleV2/RequestHandlerLib/LoggingHelpers.h b/src/AspNetCoreModuleV2/CommonLib/LoggingHelpers.h
similarity index 81%
rename from src/AspNetCoreModuleV2/RequestHandlerLib/LoggingHelpers.h
rename to src/AspNetCoreModuleV2/CommonLib/LoggingHelpers.h
index f11a4ff5f5..0c06f759cf 100644
--- a/src/AspNetCoreModuleV2/RequestHandlerLib/LoggingHelpers.h
+++ b/src/AspNetCoreModuleV2/CommonLib/LoggingHelpers.h
@@ -13,10 +13,10 @@ public:
HRESULT
CreateLoggingProvider(
bool fLoggingEnabled,
- bool fEnablePipe,
+ bool fEnableNativeLogging,
PCWSTR pwzStdOutFileName,
PCWSTR pwzApplicationPath,
- _Out_ IOutputManager** outputManager
+ std::unique_ptr& outputManager
);
};
diff --git a/src/AspNetCoreModuleV2/RequestHandlerLib/NullOutputManager.h b/src/AspNetCoreModuleV2/CommonLib/NullOutputManager.h
similarity index 100%
rename from src/AspNetCoreModuleV2/RequestHandlerLib/NullOutputManager.h
rename to src/AspNetCoreModuleV2/CommonLib/NullOutputManager.h
diff --git a/src/AspNetCoreModuleV2/RequestHandlerLib/PipeOutputManager.cpp b/src/AspNetCoreModuleV2/CommonLib/PipeOutputManager.cpp
similarity index 50%
rename from src/AspNetCoreModuleV2/RequestHandlerLib/PipeOutputManager.cpp
rename to src/AspNetCoreModuleV2/CommonLib/PipeOutputManager.cpp
index 6fdcdb078b..54fb162fe4 100644
--- a/src/AspNetCoreModuleV2/RequestHandlerLib/PipeOutputManager.cpp
+++ b/src/AspNetCoreModuleV2/CommonLib/PipeOutputManager.cpp
@@ -5,63 +5,74 @@
#include "PipeOutputManager.h"
#include "exceptions.h"
#include "SRWExclusiveLock.h"
+#include "StdWrapper.h"
+#include "ntassert.h"
#define LOG_IF_DUPFAIL(err) do { if (err == -1) { LOG_IF_FAILED(HRESULT_FROM_WIN32(_doserrno)); } } while (0, 0);
#define LOG_IF_ERRNO(err) do { if (err != 0) { LOG_IF_FAILED(HRESULT_FROM_WIN32(_doserrno)); } } while (0, 0);
-PipeOutputManager::PipeOutputManager() :
- m_dwStdErrReadTotal(0),
+PipeOutputManager::PipeOutputManager()
+ : PipeOutputManager( /* fEnableNativeLogging */ true)
+{
+}
+
+PipeOutputManager::PipeOutputManager(bool fEnableNativeLogging) :
m_hErrReadPipe(INVALID_HANDLE_VALUE),
m_hErrWritePipe(INVALID_HANDLE_VALUE),
- m_hErrThread(NULL),
+ m_hErrThread(nullptr),
+ m_dwStdErrReadTotal(0),
m_disposed(FALSE),
- m_fdPreviousStdOut(-1),
- m_fdPreviousStdErr(-1)
+ m_fEnableNativeRedirection(fEnableNativeLogging),
+ stdoutWrapper(nullptr),
+ stderrWrapper(nullptr)
{
InitializeSRWLock(&m_srwLock);
}
PipeOutputManager::~PipeOutputManager()
{
- Stop();
+ PipeOutputManager::Stop();
}
+// Start redirecting stdout and stderr into a pipe
+// Continuously read the pipe on a background thread
+// until Stop is called.
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.
+ stdoutWrapper = std::make_unique(stdout, STD_OUTPUT_HANDLE, hStdErrWritePipe, m_fEnableNativeRedirection);
+ stderrWrapper = std::make_unique(stderr, STD_ERROR_HANDLE, hStdErrWritePipe, m_fEnableNativeRedirection);
+
+ LOG_IF_FAILED(stdoutWrapper->StartRedirection());
+ LOG_IF_FAILED(stderrWrapper->StartRedirection());
+
+ // Read the stderr handle on a separate thread until we get 30Kb.
m_hErrThread = CreateThread(
- NULL, // default security attributes
+ nullptr, // default security attributes
0, // default stack size
- (LPTHREAD_START_ROUTINE)ReadStdErrHandle,
+ reinterpret_cast(ReadStdErrHandle),
this, // thread function arguments
0, // default creation flags
- NULL); // receive thread identifier
+ nullptr); // receive thread identifier
RETURN_LAST_ERROR_IF_NULL(m_hErrThread);
return S_OK;
}
+// Stop redirecting stdout and stderr into a pipe
+// This closes the background thread reading from the pipe
+// and prints any output that was captured in the pipe.
+// If more than 30Kb was written to the pipe, that output will
+// be thrown away.
HRESULT PipeOutputManager::Stop()
{
DWORD dwThreadStatus = 0;
@@ -71,57 +82,53 @@ HRESULT PipeOutputManager::Stop()
{
return S_OK;
}
+
SRWExclusiveLock lock(m_srwLock);
if (m_disposed)
{
return S_OK;
}
+
m_disposed = true;
- fflush(stdout);
- fflush(stderr);
-
- // Restore the original stdout and stderr handles of the process,
- // as the application has either finished startup or has exited.
-
- // If stdout/stderr were not set, we need to set it to NUL:
- // such that other calls to Console.WriteLine don't use an invalid handle
- FILE *stream;
-
- if (m_fdPreviousStdOut >= 0)
- {
- LOG_LAST_ERROR_IF(SetStdHandle(STD_OUTPUT_HANDLE, (HANDLE)_get_osfhandle(m_fdPreviousStdOut)));
- }
- else
- {
- LOG_IF_ERRNO(freopen_s(&stream, "NUL:", "w", stdout));
- }
-
- if (m_fdPreviousStdErr >= 0)
- {
- LOG_LAST_ERROR_IF(SetStdHandle(STD_ERROR_HANDLE, (HANDLE)_get_osfhandle(m_fdPreviousStdErr)));
- }
- else
- {
- LOG_IF_ERRNO(freopen_s(&stream, "NUL:", "w", stderr));
- }
-
+ // Both pipe wrappers duplicate the pipe writer handle
+ // meaning we are fine to close the handle too.
if (m_hErrWritePipe != INVALID_HANDLE_VALUE)
{
+ // Flush the pipe writer before closing to capture all output
+ RETURN_LAST_ERROR_IF(!FlushFileBuffers(m_hErrWritePipe));
CloseHandle(m_hErrWritePipe);
m_hErrWritePipe = INVALID_HANDLE_VALUE;
}
+ // Tell each pipe wrapper to stop redirecting output and restore the original values
+ if (stdoutWrapper != nullptr)
+ {
+ LOG_IF_FAILED(stdoutWrapper->StopRedirection());
+ }
+
+ if (stderrWrapper != nullptr)
+ {
+ LOG_IF_FAILED(stderrWrapper->StopRedirection());
+ }
+
+ // Forces ReadFile to cancel, causing the read loop to complete.
+ // Don't check return value as IO may or may not be completed already.
+ if (m_hErrThread != nullptr)
+ {
+ CancelSynchronousIo(m_hErrThread);
+ }
+
// GetExitCodeThread returns 0 on failure; thread status code is invalid.
- if (m_hErrThread != NULL &&
+ if (m_hErrThread != nullptr &&
!LOG_LAST_ERROR_IF(GetExitCodeThread(m_hErrThread, &dwThreadStatus) == 0) &&
dwThreadStatus == STILL_ACTIVE)
{
- // wait for graceful shutdown, i.e., the exit of the background thread or timeout
+ // Wait for graceful shutdown, i.e., the exit of the background thread or timeout
if (WaitForSingleObject(m_hErrThread, PIPE_OUTPUT_THREAD_TIMEOUT) != WAIT_OBJECT_0)
{
- // if the thread is still running, we need kill it first before exit to avoid AV
+ // If the thread is still running, we need kill it first before exit to avoid AV
if (!LOG_LAST_ERROR_IF(GetExitCodeThread(m_hErrThread, &dwThreadStatus) == 0) &&
dwThreadStatus == STILL_ACTIVE)
{
@@ -131,42 +138,38 @@ HRESULT PipeOutputManager::Stop()
}
}
- if (m_hErrThread != NULL)
+ if (m_hErrThread != nullptr)
{
CloseHandle(m_hErrThread);
- m_hErrThread = NULL;
+ m_hErrThread = nullptr;
}
-
if (m_hErrReadPipe != INVALID_HANDLE_VALUE)
{
CloseHandle(m_hErrReadPipe);
m_hErrReadPipe = INVALID_HANDLE_VALUE;
}
+ // If we captured any output, relog it to the original stdout
+ // Useful for the IIS Express scenario as it is running with stdout and stderr
if (GetStdOutContent(&straStdOutput))
{
- printf(straStdOutput.QueryStr());
- // Need to flush contents for the new stdout and stderr
- _flushall();
+ // printf will fail in in full IIS
+ if (printf(straStdOutput.QueryStr()) != -1)
+ {
+ // Need to flush contents for the new stdout and stderr
+ _flushall();
+ }
}
return S_OK;
}
-VOID
-PipeOutputManager::ReadStdErrHandle(
- LPVOID pContext
-)
-{
- PipeOutputManager *pLoggingProvider = (PipeOutputManager*)pContext;
- DBG_ASSERT(pLoggingProvider != NULL);
- pLoggingProvider->ReadStdErrHandleInternal();
-}
-
bool PipeOutputManager::GetStdOutContent(STRA* straStdOutput)
{
bool fLogged = false;
+
+ // TODO consider returning the file contents rather than copying.
if (m_dwStdErrReadTotal > 0)
{
if (SUCCEEDED(straStdOutput->Copy(m_pzFileContents, m_dwStdErrReadTotal)))
@@ -178,15 +181,29 @@ bool PipeOutputManager::GetStdOutContent(STRA* straStdOutput)
return fLogged;
}
-VOID
-PipeOutputManager::ReadStdErrHandleInternal(
- VOID
+void
+PipeOutputManager::ReadStdErrHandle(
+ LPVOID pContext
)
{
+ auto pLoggingProvider = static_cast(pContext);
+ DBG_ASSERT(pLoggingProvider != NULL);
+ pLoggingProvider->ReadStdErrHandleInternal();
+}
+
+void
+PipeOutputManager::ReadStdErrHandleInternal()
+{
+ // If ReadFile ever returns false, exit the thread
DWORD dwNumBytesRead = 0;
while (true)
{
- if (ReadFile(m_hErrReadPipe, &m_pzFileContents[m_dwStdErrReadTotal], MAX_PIPE_READ_SIZE - m_dwStdErrReadTotal, &dwNumBytesRead, NULL))
+ // Fill a maximum of MAX_PIPE_READ_SIZE into a buffer.
+ if (ReadFile(m_hErrReadPipe,
+ &m_pzFileContents[m_dwStdErrReadTotal],
+ MAX_PIPE_READ_SIZE - m_dwStdErrReadTotal,
+ &dwNumBytesRead,
+ nullptr))
{
m_dwStdErrReadTotal += dwNumBytesRead;
if (m_dwStdErrReadTotal >= MAX_PIPE_READ_SIZE)
@@ -194,19 +211,21 @@ PipeOutputManager::ReadStdErrHandleInternal(
break;
}
}
- else if (GetLastError() == ERROR_BROKEN_PIPE)
+ else
{
return;
}
}
- char tempBuffer[MAX_PIPE_READ_SIZE];
+ // Using std::string as a wrapper around new char[] so we don't need to call delete
+ // Also don't allocate on stack as stack size is 128KB by default.
+ std::string tempBuffer;
+ tempBuffer.resize(MAX_PIPE_READ_SIZE);
+
+ // After reading the maximum amount of data, keep reading in a loop until Stop is called on the output manager.
while (true)
{
- if (ReadFile(m_hErrReadPipe, tempBuffer, MAX_PIPE_READ_SIZE, &dwNumBytesRead, NULL))
- {
- }
- else if (GetLastError() == ERROR_BROKEN_PIPE)
+ if (!ReadFile(m_hErrReadPipe, tempBuffer.data(), MAX_PIPE_READ_SIZE, &dwNumBytesRead, nullptr))
{
return;
}
diff --git a/src/AspNetCoreModuleV2/RequestHandlerLib/PipeOutputManager.h b/src/AspNetCoreModuleV2/CommonLib/PipeOutputManager.h
similarity index 53%
rename from src/AspNetCoreModuleV2/RequestHandlerLib/PipeOutputManager.h
rename to src/AspNetCoreModuleV2/CommonLib/PipeOutputManager.h
index 3a15c2e68e..0b51ff4038 100644
--- a/src/AspNetCoreModuleV2/RequestHandlerLib/PipeOutputManager.h
+++ b/src/AspNetCoreModuleV2/CommonLib/PipeOutputManager.h
@@ -4,35 +4,41 @@
#pragma once
#include "IOutputManager.h"
+#include "StdWrapper.h"
+#include "stringu.h"
class PipeOutputManager : public IOutputManager
{
+ // Timeout to be used if a thread never exits
#define PIPE_OUTPUT_THREAD_TIMEOUT 2000
- #define MAX_PIPE_READ_SIZE 4096
+
+ // Max event log message is ~32KB, limit pipe size just below that.
+ #define MAX_PIPE_READ_SIZE 30000
public:
PipeOutputManager();
+ PipeOutputManager(bool fEnableNativeLogging);
~PipeOutputManager();
- virtual HRESULT Start() override;
- virtual HRESULT Stop() override;
- virtual bool GetStdOutContent(STRA* struStdOutput) override;
+ HRESULT Start() override;
+ HRESULT Stop() override;
+ bool GetStdOutContent(STRA* straStdOutput) override;
// Thread functions
- VOID ReadStdErrHandleInternal(VOID);
+ void ReadStdErrHandleInternal();
- static
- VOID ReadStdErrHandle(LPVOID pContext);
+ static void ReadStdErrHandle(LPVOID pContext);
private:
+
HANDLE m_hErrReadPipe;
HANDLE m_hErrWritePipe;
STRU m_struLogFilePath;
HANDLE m_hErrThread;
CHAR m_pzFileContents[MAX_PIPE_READ_SIZE] = { 0 };
DWORD m_dwStdErrReadTotal;
- SRWLOCK m_srwLock;
- int m_fdPreviousStdOut;
- int m_fdPreviousStdErr;
+ SRWLOCK m_srwLock {};
BOOL m_disposed;
+ BOOL m_fEnableNativeRedirection;
+ std::unique_ptr stdoutWrapper;
+ std::unique_ptr stderrWrapper;
};
-
diff --git a/src/AspNetCoreModuleV2/CommonLib/StdWrapper.cpp b/src/AspNetCoreModuleV2/CommonLib/StdWrapper.cpp
new file mode 100644
index 0000000000..dffaa491c5
--- /dev/null
+++ b/src/AspNetCoreModuleV2/CommonLib/StdWrapper.cpp
@@ -0,0 +1,148 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for license information.
+
+#include "stdafx.h"
+#include "StdWrapper.h"
+#include "exceptions.h"
+#include "LoggingHelpers.h"
+#include
+#include
+
+StdWrapper::StdWrapper(FILE* stdStream, DWORD stdHandleNumber, HANDLE handleToRedirectTo, BOOL fEnableNativeRedirection)
+ : m_previousFileDescriptor(0),
+ m_stdStream(stdStream),
+ m_stdHandleNumber(stdHandleNumber),
+ m_fEnableNativeRedirection(fEnableNativeRedirection),
+ m_handleToRedirectTo(handleToRedirectTo),
+ m_redirectedFile(nullptr)
+{
+}
+
+StdWrapper::~StdWrapper() = default;
+
+// Redirects stdout/stderr to the provided handle.
+// Example:
+// If the handleToRedirecTo = 0x24
+// Before:
+// _fileno(stdout) = 1
+// GetStdHandle(STD_OUTPUT_HANDLE) = 0x20
+// After:
+// _fileno(stdout) = 3
+// GetStdHandle(STD_OUTPUT_HANDLE) = 0x28 <- Duplicated from 0x24
+HRESULT
+StdWrapper::StartRedirection()
+{
+ HANDLE stdHandle;
+
+ // In IIS, stdout and stderr are set to null as w3wp is created with DETACHED_PROCESS,
+ // so fileno(m_stdStream) returns -2.
+ // Open a null file such that undoing the redirection succeeds and _dup2 works.
+ // m_previousFileDescriptor will be used for restoring stdout/stderr
+ if (_fileno(m_stdStream) == -2)
+ {
+ freopen_s((FILE**)&m_stdStream, "nul", "w", m_stdStream);
+ m_previousFileDescriptor = _dup(_fileno(m_stdStream));
+ }
+ else
+ {
+ m_previousFileDescriptor = _dup(_fileno(m_stdStream));
+ }
+
+ if (!m_fEnableNativeRedirection)
+ {
+ RETURN_LAST_ERROR_IF(!SetStdHandle(m_stdHandleNumber, m_handleToRedirectTo));
+
+ return S_OK;
+ }
+ // After setting the std handle, we need to set stdout/stderr to the current
+ // output/error handle.
+
+ // Duplicate the handle before opening the handle and associating a file pointer.
+ // If we don't by calling close on the file, the same handle value will be closed
+ // multiple times.
+ // Note, by calling duplicate handle, the new handle returned will have a different value
+ // than the original, but point to the same underlying file object.
+ RETURN_LAST_ERROR_IF(!DuplicateHandle(
+ /* hSourceProcessHandle*/ GetCurrentProcess(),
+ /* hSourceHandle */ m_handleToRedirectTo,
+ /* hTargetProcessHandle */ GetCurrentProcess(),
+ /* lpTargetHandle */&stdHandle,
+ /* dwDesiredAccess */ 0, // dwDesired is ignored if DUPLICATE_SAME_ACCESS is specified
+ /* bInheritHandle */ TRUE,
+ /* dwOptions */ DUPLICATE_SAME_ACCESS));
+
+ RETURN_LAST_ERROR_IF(!SetStdHandle(m_stdHandleNumber, stdHandle));
+
+ // _open_osfhandle will associate a filedescriptor with the handle.
+ const auto fileDescriptor = _open_osfhandle(reinterpret_cast(stdHandle), _O_WTEXT | _O_TEXT);
+
+ if (fileDescriptor == -1)
+ {
+ RETURN_IF_FAILED(HRESULT_FROM_WIN32(ERROR_FILE_INVALID));
+ }
+
+ m_redirectedFile = _fdopen(fileDescriptor, "w");
+
+ if (m_redirectedFile == nullptr)
+ {
+ RETURN_IF_FAILED(HRESULT_FROM_WIN32(ERROR_FILE_INVALID));
+ }
+
+ // Set stdout/stderr to the newly created file.
+ const auto dup2Result = _dup2(_fileno(m_redirectedFile), _fileno(m_stdStream));
+
+ if (dup2Result != 0)
+ {
+ RETURN_IF_FAILED(HRESULT_FROM_WIN32(ERROR_FILE_INVALID));
+ }
+
+ // Removes buffering from the output
+ if (setvbuf(m_stdStream, nullptr, _IONBF, 0) != 0)
+ {
+ RETURN_IF_FAILED(HRESULT_FROM_WIN32(ERROR_FILE_INVALID));
+ }
+
+ return S_OK;
+}
+
+// Redirects stdout/stderr back to the original stdout/stderr.
+// Note, this will not restore the original handle values returned by GetStdHandle,
+// rather a duplicated number. This is because the original handle value is invalid
+// due to dup2 closing the file originally in stdout/stderr
+HRESULT
+StdWrapper::StopRedirection() const
+{
+ // After setting the std handle, we need to set stdout/stderr to the current
+ // output/error handle.
+ FILE * file = _fdopen(m_previousFileDescriptor, "w");
+ if (file == nullptr)
+ {
+ RETURN_IF_FAILED(HRESULT_FROM_WIN32(ERROR_FILE_INVALID));
+ }
+
+ RETURN_LAST_ERROR_IF(!SetStdHandle(m_stdHandleNumber, reinterpret_cast(_get_osfhandle(m_previousFileDescriptor))));
+
+ if (!m_fEnableNativeRedirection)
+ {
+ return S_OK;
+ }
+
+ // Set stdout/stderr to the newly created file output.
+ const auto dup2Result = _dup2(_fileno(file), _fileno(m_stdStream));
+ if (dup2Result != 0)
+ {
+ RETURN_IF_FAILED(HRESULT_FROM_WIN32(ERROR_FILE_INVALID));
+ }
+
+ if (setvbuf(m_stdStream, nullptr, _IONBF, 0) != 0)
+ {
+ RETURN_IF_FAILED(HRESULT_FROM_WIN32(ERROR_FILE_INVALID));
+ }
+
+ if (fclose(m_redirectedFile) != 0)
+ {
+ RETURN_IF_FAILED(HRESULT_FROM_WIN32(ERROR_FILE_INVALID));
+ }
+
+ return S_OK;
+}
diff --git a/src/AspNetCoreModuleV2/CommonLib/StdWrapper.h b/src/AspNetCoreModuleV2/CommonLib/StdWrapper.h
new file mode 100644
index 0000000000..f03b2ff060
--- /dev/null
+++ b/src/AspNetCoreModuleV2/CommonLib/StdWrapper.h
@@ -0,0 +1,25 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for license information.
+
+#pragma once
+
+#include
+
+// Wraps stdout/stderr stream, modifying them to redirect to the given handle
+class StdWrapper
+{
+public:
+ StdWrapper(FILE* stdStream, DWORD stdHandleNumber, HANDLE handleToRedirectTo, BOOL fEnableNativeRedirection);
+ ~StdWrapper();
+ HRESULT StartRedirection();
+ HRESULT StopRedirection() const;
+
+private:
+ int m_previousFileDescriptor;
+ FILE* m_stdStream;
+ DWORD m_stdHandleNumber;
+ BOOL m_fEnableNativeRedirection;
+ HANDLE m_handleToRedirectTo;
+ FILE* m_redirectedFile;
+};
+
diff --git a/src/AspNetCoreModuleV2/CommonLib/aspnetcore_msg.mc b/src/AspNetCoreModuleV2/CommonLib/aspnetcore_msg.mc
index c71cbfeee2..5b4c244c63 100644
--- a/src/AspNetCoreModuleV2/CommonLib/aspnetcore_msg.mc
+++ b/src/AspNetCoreModuleV2/CommonLib/aspnetcore_msg.mc
@@ -177,19 +177,19 @@ Language=English
.
Messageid=1025
-SymbolicName=ASPNETCORE_EVENT_GENERAL_INFO_MSG
+SymbolicName=ASPNETCORE_EVENT_GENERAL_INFO
Language=English
%1
.
Messageid=1026
-SymbolicName=ASPNETCORE_EVENT_GENERAL_WARNING_MSG
+SymbolicName=ASPNETCORE_EVENT_GENERAL_WARNING
Language=English
%1
.
Messageid=1027
-SymbolicName=ASPNETCORE_EVENT_GENERAL_ERROR_MSG
+SymbolicName=ASPNETCORE_EVENT_GENERAL_ERROR
Language=English
%1
.
diff --git a/src/AspNetCoreModuleV2/CommonLib/exceptions.h b/src/AspNetCoreModuleV2/CommonLib/exceptions.h
index ac05f910c1..bd6f30af33 100644
--- a/src/AspNetCoreModuleV2/CommonLib/exceptions.h
+++ b/src/AspNetCoreModuleV2/CommonLib/exceptions.h
@@ -26,6 +26,8 @@
#endif
#define OBSERVE_CAUGHT_EXCEPTION() CaughtExceptionHResult(LOCATION_INFO);
+#define RETURN_HR(hr) do { HRESULT __hrRet = hr; if (FAILED(__hrRet)) { LogHResultFailed(LOCATION_INFO, __hrRet); } return __hrRet; } while (0, 0)
+#define RETURN_LAST_ERROR() do { return LogLastError(LOCATION_INFO); } while (0, 0)
#define RETURN_IF_FAILED(hr) do { HRESULT __hrRet = hr; if (FAILED(__hrRet)) { LogHResultFailed(LOCATION_INFO, __hrRet); return __hrRet; }} while (0, 0)
#define RETURN_CAUGHT_EXCEPTION() return CaughtExceptionHResult(LOCATION_INFO);
#define RETURN_LAST_ERROR_IF(condition) do { if (condition) { return LogLastError(LOCATION_INFO); }} while (0, 0)
diff --git a/src/AspNetCoreModuleV2/CommonLib/resources.h b/src/AspNetCoreModuleV2/CommonLib/resources.h
index 63e0e9b163..82f22c52c0 100644
--- a/src/AspNetCoreModuleV2/CommonLib/resources.h
+++ b/src/AspNetCoreModuleV2/CommonLib/resources.h
@@ -17,7 +17,7 @@
#define ASPNETCORE_EVENT_PROCESS_START_ERROR_MSG L"Application '%s' with physical root '%s' failed to start process with commandline '%s' at stage '%s', ErrorCode = '0x%x', assigned port %d, retryCounter '%d'."
#define ASPNETCORE_EVENT_PROCESS_START_FAILURE_MSG L"Application '%s' with physical root '%s' failed to start process with commandline '%s' with multiple retries. The last try of listening port is '%d'. See previous warnings for details."
#define ASPNETCORE_EVENT_PROCESS_START_STATUS_ERROR_MSG L"Application '%s' with physical root '%s' failed to start process with commandline '%s' , ErrorCode = '0x%x', processId '%d', processStatus '%d'."
-#define ASPNETCORE_EVENT_PROCESS_START_PORTSETUP_ERROR_MSG L"Application '%s' with physical root '%s' failed to choose listen port '%d' given port rang '%d - %d', EorrorCode = '0x%x'. If environment variable 'ASPNETCORE_PORT' was set, try removing it such that a random port is selected instead."
+#define ASPNETCORE_EVENT_PROCESS_START_PORTSETUP_ERROR_MSG L"Application '%s' with physical root '%s' failed to choose listen port '%d' given port range '%d - %d', ErrorCode = '0x%x'. If environment variable 'ASPNETCORE_PORT' was set, try removing it such that a random port is selected instead."
#define ASPNETCORE_EVENT_PROCESS_START_WRONGPORT_ERROR_MSG L"Application '%s' with physical root '%s' created process with commandline '%s' but failed to listen on the given port '%d'"
#define ASPNETCORE_EVENT_PROCESS_START_NOTREADY_ERROR_MSG L"Application '%s' with physical root '%s' created process with commandline '%s' but either crashed or did not respond or did not listen on the given port '%d', ErrorCode = '0x%x'"
#define ASPNETCORE_EVENT_PROCESS_SHUTDOWN_MSG L"Application '%s' with physical root '%s' shut down process with Id '%d' listening on port '%d'"
@@ -31,8 +31,8 @@
#define ASPNETCORE_EVENT_MIXED_HOSTING_MODEL_ERROR_MSG L"Mixed hosting model is not supported. Application '%s' configured with different hostingModel value '%d' other than the one of running application(s)."
#define ASPNETCORE_EVENT_UNKNOWN_HOSTING_MODEL_ERROR_MSG L"Unknown hosting model '%s'. Please specify either hostingModel=\"inprocess\" or hostingModel=\"outofprocess\" in the web.config file."
#define ASPNETCORE_EVENT_ADD_APPLICATION_ERROR_MSG L"Failed to start application '%s', ErrorCode '0x%x'."
-#define ASPNETCORE_EVENT_INPROCESS_THREAD_EXIT_STDOUT_MSG L"Application '%s' with physical root '%s' hit unexpected managed background thread exit, ErrorCode = '0x%x. Last 4KB characters of captured stdout and stderr logs:\r\n%s"
-#define ASPNETCORE_EVENT_INPROCESS_THREAD_EXIT_MSG L"Application '%s' with physical root '%s' hit unexpected managed background thread exit, ErrorCode = '0x%x. Please check the stderr logs for more information."
+#define ASPNETCORE_EVENT_INPROCESS_THREAD_EXIT_STDOUT_MSG L"Application '%s' with physical root '%s' hit unexpected managed background thread exit, ErrorCode = '0x%x'. Last 4KB characters of captured stdout and stderr logs:\r\n%s"
+#define ASPNETCORE_EVENT_INPROCESS_THREAD_EXIT_MSG L"Application '%s' with physical root '%s' hit unexpected managed background thread exit, ErrorCode = '0x%x'. Please check the stderr logs for more information."
#define ASPNETCORE_EVENT_APP_IN_SHUTDOWN_MSG L"Application shutting down."
#define ASPNETCORE_EVENT_RECYCLE_APPOFFLINE_MSG L"Application '%s' was recycled after detecting the app_offline file."
#define ASPNETCORE_EVENT_MONITOR_APPOFFLINE_ERROR_MSG L"Monitoring app_offline.htm failed for application '%s', ErrorCode '0x%x'. "
@@ -43,9 +43,11 @@
#define ASPNETCORE_EVENT_PORTABLE_APP_DOTNET_MISSING_MSG L"Could not find dotnet.exe on the system PATH environment variable for portable application '%s'. Check that a valid path to dotnet is on the PATH and the bitness of dotnet matches the bitness of the IIS worker process. ErrorCode = '0x%x'."
#define ASPNETCORE_EVENT_HOSTFXR_DIRECTORY_NOT_FOUND_MSG L"Could not find the hostfxr directory '%s' in the dotnet directory. ErrorCode = '0x%x'."
#define ASPNETCORE_EVENT_HOSTFXR_DLL_NOT_FOUND_MSG L"Could not find hostfxr.dll in '%s'. ErrorCode = '0x%x'."
+#define ASPNETCORE_EVENT_HOSTFXR_DLL_INVALID_VERSION_MSG L"Hostfxr version used does not support 'hostfxr_get_native_search_directories', update the version of hostfxr to a higher version. Path to hostfxr: '%s'."
+#define ASPNETCORE_EVENT_APPLICATION_EXE_NOT_FOUND_LEVEL EVENTLOG_ERROR_TYPE
#define ASPNETCORE_EVENT_APPLICATION_EXE_NOT_FOUND_MSG L"Could not find application executable in '%s'. ErrorCode = '0x%x'."
#define ASPNETCORE_EVENT_INPROCESS_THREAD_EXCEPTION_MSG L"Application '%s' with physical root '%s' hit unexpected managed exception, ErrorCode = '0x%x. Please check the stderr logs for more information."
#define ASPNETCORE_EVENT_INVALID_PROCESS_PATH_MSG L"Invalid or unknown processPath provided in web.config: processPath = '%s', ErrorCode = '0x%x'."
-#define ASPNETCORE_EVENT_INPROCESS_RH_MISSING_MSG L"Could not find the assembly '%s' for in-process application. Please confirm the Microsoft.AspNetCore.Server.IIS package is referenced in your application."
+#define ASPNETCORE_EVENT_INPROCESS_RH_ERROR_MSG L"Could not find the assembly '%s' for in-process application. Please confirm the Microsoft.AspNetCore.Server.IIS package is referenced in your application. Captured output: %s"
#define ASPNETCORE_EVENT_OUT_OF_PROCESS_RH_MISSING_MSG L"Could not find the assembly '%s' for out-of-process application. Please confirm the assembly is installed correctly for IIS or IISExpress."
#define ASPNETCORE_EVENT_INPROCESS_START_SUCCESS_MSG L"Application '%s' started the coreclr in-process successfully."
diff --git a/src/AspNetCoreModuleV2/CommonLib/sttimer.h b/src/AspNetCoreModuleV2/CommonLib/sttimer.h
index 0ebbdbd822..26d79d0737 100644
--- a/src/AspNetCoreModuleV2/CommonLib/sttimer.h
+++ b/src/AspNetCoreModuleV2/CommonLib/sttimer.h
@@ -6,6 +6,7 @@
#ifndef _STTIMER_H
#define _STTIMER_H
+#include "stringu.h"
class STTIMER
{
diff --git a/src/AspNetCoreModuleV2/InProcessRequestHandler/inprocessapplication.cpp b/src/AspNetCoreModuleV2/InProcessRequestHandler/inprocessapplication.cpp
index 352ec7b093..43a4071cf5 100644
--- a/src/AspNetCoreModuleV2/InProcessRequestHandler/inprocessapplication.cpp
+++ b/src/AspNetCoreModuleV2/InProcessRequestHandler/inprocessapplication.cpp
@@ -102,12 +102,6 @@ IN_PROCESS_APPLICATION::StopInternal(bool fServerInitiated)
}
}
- if (m_pLoggerProvider != NULL)
- {
- delete m_pLoggerProvider;
- m_pLoggerProvider = NULL;
- }
-
Finished:
if (FAILED(hr))
@@ -256,24 +250,7 @@ IN_PROCESS_APPLICATION::LoadManagedApplication
}
{
- // Set up stdout redirect
-
SRWExclusiveLock lock(m_stateLock);
- if (m_pLoggerProvider == NULL)
- {
- hr = LoggingHelpers::CreateLoggingProvider(
- m_pConfig->QueryStdoutLogEnabled(),
- !GetConsoleWindow(),
- m_pConfig->QueryStdoutLogFile()->QueryStr(),
- m_pConfig->QueryApplicationPhysicalPath()->QueryStr(),
- &m_pLoggerProvider);
- if (FAILED(hr))
- {
- goto Finished;
- }
-
- LOG_IF_FAILED(m_pLoggerProvider->Start());
- }
if (m_status != MANAGED_APPLICATION_STATUS::STARTING)
{
@@ -461,6 +438,20 @@ IN_PROCESS_APPLICATION::ExecuteApplication(
FINISHED_IF_FAILED(SetEnvironementVariablesOnWorkerProcess());
}
+ LOG_INFO("Starting managed application");
+
+ if (m_pLoggerProvider == NULL)
+ {
+ FINISHED_IF_FAILED(hr = LoggingHelpers::CreateLoggingProvider(
+ m_pConfig->QueryStdoutLogEnabled(),
+ !m_pHttpServer.IsCommandLineLaunch(),
+ m_pConfig->QueryStdoutLogFile()->QueryStr(),
+ m_pConfig->QueryApplicationPhysicalPath()->QueryStr(),
+ m_pLoggerProvider));
+
+ LOG_IF_FAILED(m_pLoggerProvider->Start());
+ }
+
// There can only ever be a single instance of .NET Core
// loaded in the process but we need to get config information to boot it up in the
// first place. This is happening in an execute request handler and everyone waits
@@ -482,7 +473,7 @@ Finished:
//
m_status = MANAGED_APPLICATION_STATUS::SHUTDOWN;
m_fShutdownCalledFromManaged = TRUE;
- FreeLibrary(hModule);
+
m_pLoggerProvider->Stop();
if (!m_fShutdownCalledFromNative)
@@ -545,7 +536,6 @@ IN_PROCESS_APPLICATION::RunDotnetApplication(DWORD argc, CONST PCWSTR* argv, hos
__try
{
- LOG_INFO("Starting managed application");
m_ProcessExitCode = pProc(argc, argv);
if (m_ProcessExitCode != 0)
{
diff --git a/src/AspNetCoreModuleV2/InProcessRequestHandler/inprocessapplication.h b/src/AspNetCoreModuleV2/InProcessRequestHandler/inprocessapplication.h
index 8993d7fc8e..10149cf3f3 100644
--- a/src/AspNetCoreModuleV2/InProcessRequestHandler/inprocessapplication.h
+++ b/src/AspNetCoreModuleV2/InProcessRequestHandler/inprocessapplication.h
@@ -150,7 +150,7 @@ private:
static IN_PROCESS_APPLICATION* s_Application;
- IOutputManager* m_pLoggerProvider;
+ std::unique_ptr m_pLoggerProvider;
static const LPCSTR s_exeLocationParameterName;
diff --git a/src/AspNetCoreModuleV2/OutOfProcessRequestHandler/OutOfProcessRequestHandler.vcxproj b/src/AspNetCoreModuleV2/OutOfProcessRequestHandler/OutOfProcessRequestHandler.vcxproj
index 2da0550413..df9c00ebb1 100644
--- a/src/AspNetCoreModuleV2/OutOfProcessRequestHandler/OutOfProcessRequestHandler.vcxproj
+++ b/src/AspNetCoreModuleV2/OutOfProcessRequestHandler/OutOfProcessRequestHandler.vcxproj
@@ -224,7 +224,6 @@
-
diff --git a/src/AspNetCoreModuleV2/OutOfProcessRequestHandler/dllmain.cpp b/src/AspNetCoreModuleV2/OutOfProcessRequestHandler/dllmain.cpp
index d77c5c47d8..25e8054318 100644
--- a/src/AspNetCoreModuleV2/OutOfProcessRequestHandler/dllmain.cpp
+++ b/src/AspNetCoreModuleV2/OutOfProcessRequestHandler/dllmain.cpp
@@ -121,28 +121,29 @@ EnsureOutOfProcessInitializtion()
DBG_ASSERT(g_pHttpServer);
HRESULT hr = S_OK;
- BOOL fLocked = FALSE;
if (g_fOutOfProcessInitializeError)
{
- hr = E_NOT_VALID_STATE;
- goto Finished;
+ FINISHED(E_NOT_VALID_STATE);
}
- if (!g_fOutOfProcessInitialize)
+ if (g_fOutOfProcessInitialize)
{
- AcquireSRWLockExclusive(&g_srwLockRH);
- fLocked = TRUE;
+ FINISHED(S_OK);
+ }
+
+ {
+ auto lock = SRWExclusiveLock(g_srwLockRH);
+
if (g_fOutOfProcessInitializeError)
{
- hr = E_NOT_VALID_STATE;
- goto Finished;
+ FINISHED(E_NOT_VALID_STATE);
}
if (g_fOutOfProcessInitialize)
{
// Done by another thread
- goto Finished;
+ FINISHED(S_OK);
}
g_hWinHttpModule = GetModuleHandle(TEXT("winhttp.dll"));
@@ -150,7 +151,7 @@ EnsureOutOfProcessInitializtion()
g_hAspNetCoreModule = GetModuleHandle(TEXT("aspnetcorev2.dll"));
hr = WINHTTP_HELPER::StaticInitialize();
- if (FAILED(hr))
+ if (FAILED_LOG(hr))
{
if (hr == HRESULT_FROM_WIN32(ERROR_PROC_NOT_FOUND))
{
@@ -158,7 +159,7 @@ EnsureOutOfProcessInitializtion()
}
else
{
- goto Finished;
+ FINISHED(hr);
}
}
@@ -167,11 +168,7 @@ EnsureOutOfProcessInitializtion()
WINHTTP_NO_PROXY_NAME,
WINHTTP_NO_PROXY_BYPASS,
WINHTTP_FLAG_ASYNC);
- if (g_hWinhttpSession == NULL)
- {
- hr = HRESULT_FROM_WIN32(GetLastError());
- goto Finished;
- }
+ FINISHED_LAST_ERROR_IF(g_hWinhttpSession == NULL);
//
// Don't set non-blocking callbacks WINHTTP_OPTION_ASSURED_NON_BLOCKING_CALLBACKS,
@@ -182,65 +179,33 @@ EnsureOutOfProcessInitializtion()
//
// Setup the callback function
//
- if (WinHttpSetStatusCallback(g_hWinhttpSession,
+ FINISHED_LAST_ERROR_IF(WinHttpSetStatusCallback(g_hWinhttpSession,
FORWARDING_HANDLER::OnWinHttpCompletion,
(WINHTTP_CALLBACK_FLAG_ALL_COMPLETIONS |
WINHTTP_CALLBACK_STATUS_SENDING_REQUEST),
- NULL) == WINHTTP_INVALID_STATUS_CALLBACK)
- {
- hr = HRESULT_FROM_WIN32(GetLastError());
- goto Finished;
- }
+ NULL) == WINHTTP_INVALID_STATUS_CALLBACK);
//
// Make sure we see the redirects (rather than winhttp doing it
// automatically)
//
DWORD dwRedirectOption = WINHTTP_OPTION_REDIRECT_POLICY_NEVER;
- if (!WinHttpSetOption(g_hWinhttpSession,
+ FINISHED_LAST_ERROR_IF(!WinHttpSetOption(g_hWinhttpSession,
WINHTTP_OPTION_REDIRECT_POLICY,
&dwRedirectOption,
- sizeof(dwRedirectOption)))
- {
- hr = HRESULT_FROM_WIN32(GetLastError());
- goto Finished;
- }
+ sizeof(dwRedirectOption)));
g_dwTlsIndex = TlsAlloc();
- if (g_dwTlsIndex == TLS_OUT_OF_INDEXES)
- {
- hr = HRESULT_FROM_WIN32(GetLastError());
- goto Finished;
- }
-
- hr = ALLOC_CACHE_HANDLER::StaticInitialize();
- if (FAILED(hr))
- {
- goto Finished;
- }
-
- hr = FORWARDING_HANDLER::StaticInitialize(g_fEnableReferenceCountTracing);
- if (FAILED(hr))
- {
- goto Finished;
- }
-
- hr = WEBSOCKET_HANDLER::StaticInitialize(g_fEnableReferenceCountTracing);
- if (FAILED(hr))
- {
- goto Finished;
- }
+ FINISHED_LAST_ERROR_IF(g_dwTlsIndex == TLS_OUT_OF_INDEXES);
+ FINISHED_IF_FAILED(ALLOC_CACHE_HANDLER::StaticInitialize());
+ FINISHED_IF_FAILED(FORWARDING_HANDLER::StaticInitialize(g_fEnableReferenceCountTracing));
+ FINISHED_IF_FAILED(WEBSOCKET_HANDLER::StaticInitialize(g_fEnableReferenceCountTracing));
}
-
Finished:
if (FAILED(hr))
{
g_fOutOfProcessInitializeError = TRUE;
}
- if (fLocked)
- {
- ReleaseSRWLockExclusive(&g_srwLockRH);
- }
return hr;
}
diff --git a/src/AspNetCoreModuleV2/OutOfProcessRequestHandler/forwarderconnection.cpp b/src/AspNetCoreModuleV2/OutOfProcessRequestHandler/forwarderconnection.cpp
index 0369edcce9..ee49e99242 100644
--- a/src/AspNetCoreModuleV2/OutOfProcessRequestHandler/forwarderconnection.cpp
+++ b/src/AspNetCoreModuleV2/OutOfProcessRequestHandler/forwarderconnection.cpp
@@ -2,12 +2,13 @@
// Licensed under the MIT License. See License.txt in the project root for license information.
#include "forwarderconnection.h"
+#include "exceptions.h"
FORWARDER_CONNECTION::FORWARDER_CONNECTION(
VOID
) : m_cRefs (1),
m_hConnection (NULL)
-{
+{
}
HRESULT
@@ -15,38 +16,19 @@ FORWARDER_CONNECTION::Initialize(
DWORD dwPort
)
{
- HRESULT hr = S_OK;
-
- hr = m_ConnectionKey.Initialize( dwPort );
- if ( FAILED( hr ) )
- {
- goto Finished;
- }
-
+ RETURN_IF_FAILED(m_ConnectionKey.Initialize( dwPort ));
m_hConnection = WinHttpConnect(g_hWinhttpSession,
L"127.0.0.1",
(USHORT) dwPort,
0);
- if (m_hConnection == NULL)
- {
- hr = HRESULT_FROM_WIN32(GetLastError());
- goto Finished;
- }
-
+ RETURN_LAST_ERROR_IF_NULL(m_hConnection);
//
// Since WinHttp will not emit WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
// when closing WebSocket handle on Win8. Register callback at Connect level as a workaround
//
- if (WinHttpSetStatusCallback(m_hConnection,
+ RETURN_LAST_ERROR_IF (WinHttpSetStatusCallback(m_hConnection,
FORWARDING_HANDLER::OnWinHttpCompletion,
WINHTTP_CALLBACK_FLAG_HANDLES,
- NULL) == WINHTTP_INVALID_STATUS_CALLBACK)
- {
- hr = HRESULT_FROM_WIN32(GetLastError());
- goto Finished;
- }
-
-Finished:
-
- return hr;
+ NULL) == WINHTTP_INVALID_STATUS_CALLBACK);
+ return S_OK;
}
diff --git a/src/AspNetCoreModuleV2/OutOfProcessRequestHandler/forwardinghandler.cpp b/src/AspNetCoreModuleV2/OutOfProcessRequestHandler/forwardinghandler.cpp
index f1bcb7a2cc..e06b15f805 100644
--- a/src/AspNetCoreModuleV2/OutOfProcessRequestHandler/forwardinghandler.cpp
+++ b/src/AspNetCoreModuleV2/OutOfProcessRequestHandler/forwardinghandler.cpp
@@ -3,6 +3,7 @@
#include "forwardinghandler.h"
#include "url_utility.h"
+#include "exceptions.h"
// Just to be aware of the FORWARDING_HANDLER object size.
C_ASSERT(sizeof(FORWARDING_HANDLER) <= 632);
@@ -140,7 +141,7 @@ FORWARDING_HANDLER::OnExecuteRequestHandler()
}
hr = pApplication->GetProcess(&pServerProcess);
- if (FAILED(hr))
+ if (FAILED_LOG(hr))
{
fFailedToStartKestrel = TRUE;
goto Failure;
@@ -165,7 +166,7 @@ FORWARDING_HANDLER::OnExecuteRequestHandler()
//
// parse original url
//
- if (FAILED(hr = URL_UTILITY::SplitUrl(pRequest->GetRawHttpRequest()->CookedUrl.pFullUrl,
+ if (FAILED_LOG(hr = URL_UTILITY::SplitUrl(pRequest->GetRawHttpRequest()->CookedUrl.pFullUrl,
&fSecure,
&strDestination,
&strUrl)))
@@ -173,7 +174,7 @@ FORWARDING_HANDLER::OnExecuteRequestHandler()
goto Failure;
}
- if (FAILED(hr = URL_UTILITY::EscapeAbsPath(pRequest, &struEscapedUrl)))
+ if (FAILED_LOG(hr = URL_UTILITY::EscapeAbsPath(pRequest, &struEscapedUrl)))
{
goto Failure;
}
@@ -200,7 +201,7 @@ FORWARDING_HANDLER::OnExecuteRequestHandler()
hConnect,
&struEscapedUrl,
pServerProcess);
- if (FAILED(hr))
+ if (FAILED_LOG(hr))
{
goto Failure;
}
@@ -222,7 +223,7 @@ FORWARDING_HANDLER::OnExecuteRequestHandler()
SetConnectionModuleContext(m_pDisconnect,
m_pModuleId);
DBG_ASSERT(hr != HRESULT_FROM_WIN32(ERROR_ALREADY_ASSIGNED));
- if (FAILED(hr))
+ if (FAILED_LOG(hr))
{
goto Failure;
}
@@ -477,7 +478,7 @@ REQUEST_NOTIFICATION_STATUS
InterlockedIncrement(&m_dwHandlers);
}
- if (FAILED(hr))
+ if (FAILED_LOG(hr))
{
// This failure could happen when client disconnect happens or backend server fails
// after websocket upgrade
@@ -514,7 +515,7 @@ REQUEST_NOTIFICATION_STATUS
// failure, if there is more data available from WinHTTP, read it
// or else ask if there is more.
//
- if (FAILED(hrCompletionStatus))
+ if (FAILED_LOG(hrCompletionStatus))
{
hr = hrCompletionStatus;
fClientError = TRUE;
@@ -522,7 +523,7 @@ REQUEST_NOTIFICATION_STATUS
}
hr = OnReceivingResponse();
- if (FAILED(hr))
+ if (FAILED_LOG(hr))
{
goto Failure;
}
@@ -533,7 +534,7 @@ REQUEST_NOTIFICATION_STATUS
hr = OnSendingRequest(cbCompletion,
hrCompletionStatus,
&fClientError);
- if (FAILED(hr))
+ if (FAILED_LOG(hr))
{
goto Failure;
}
@@ -730,7 +731,7 @@ HRESULT
hr = sm_pAlloc->Initialize(sizeof(FORWARDING_HANDLER),
64); // nThreshold
- if (FAILED(hr))
+ if (FAILED_LOG(hr))
{
goto Finished;
}
@@ -743,14 +744,14 @@ HRESULT
}
hr = sm_pResponseHeaderHash->Initialize();
- if (FAILED(hr))
+ if (FAILED_LOG(hr))
{
goto Finished;
}
// Initialize PROTOCOL_CONFIG
hr = sm_ProtocolConfig.Initialize();
- if (FAILED(hr))
+ if (FAILED_LOG(hr))
{
goto Finished;
}
@@ -786,7 +787,7 @@ HRESULT