99#include " StdWrapper.h"
1010#include " ntassert.h"
1111#include " StringHelpers.h"
12-
13- #define LOG_IF_DUPFAIL (err ) do { if (err == -1 ) { LOG_IF_FAILED (HRESULT_FROM_WIN32 (_doserrno)); } } while (0 , 0 );
14- #define LOG_IF_ERRNO (err ) do { if (err != 0 ) { LOG_IF_FAILED (HRESULT_FROM_WIN32 (_doserrno)); } } while (0 , 0 );
15-
12+ #include " Environment.h"
1613
1714StandardStreamRedirection::StandardStreamRedirection (RedirectionOutput& output, bool commandLineLaunch) :
1815 m_output(output),
@@ -23,6 +20,28 @@ StandardStreamRedirection::StandardStreamRedirection(RedirectionOutput& output,
2320 m_commandLineLaunch(commandLineLaunch)
2421{
2522 TryStartRedirection ();
23+
24+ // Allow users to override the default termination timeout for the redirection thread.
25+ auto timeoutMsStr = Environment::GetEnvironmentVariableValue (L" ASPNETCORE_OUTPUT_REDIRECTION_TERMINATION_TIMEOUT_MS" );
26+ if (timeoutMsStr.has_value ())
27+ {
28+ try
29+ {
30+ int timeoutMs = std::stoi (timeoutMsStr.value ());
31+ if (timeoutMs > 0 && timeoutMs <= PIPE_OUTPUT_THREAD_TIMEOUT_MS_MAX)
32+ {
33+ m_terminationTimeoutMs = timeoutMs;
34+ }
35+ else
36+ {
37+ LOG_WARN (L" ASPNETCORE_OUTPUT_REDIRECTION_TERMINATION_TIMEOUT_MS must be an integer between 0 and 1800000. Ignoring." );
38+ }
39+ }
40+ catch (...)
41+ {
42+ LOG_WARN (L" ASPNETCORE_OUTPUT_REDIRECTION_TERMINATION_TIMEOUT_MS must be an integer between 0 and 1800000. Ignoring." );
43+ }
44+ }
2645}
2746
2847StandardStreamRedirection::~StandardStreamRedirection () noexcept (false )
@@ -80,8 +99,6 @@ void StandardStreamRedirection::Start()
8099// be thrown away.
81100void StandardStreamRedirection::Stop ()
82101{
83- DWORD dwThreadStatus = 0 ;
84-
85102 if (m_disposed)
86103 {
87104 return ;
@@ -126,12 +143,13 @@ void StandardStreamRedirection::Stop()
126143 }
127144
128145 // GetExitCodeThread returns 0 on failure; thread status code is invalid.
146+ DWORD dwThreadStatus = 0 ;
129147 if (m_hErrThread != nullptr &&
130148 !LOG_LAST_ERROR_IF (!GetExitCodeThread (m_hErrThread, &dwThreadStatus)) &&
131149 dwThreadStatus == STILL_ACTIVE)
132150 {
133151 // Wait for graceful shutdown, i.e., the exit of the background thread or timeout
134- if (WaitForSingleObject (m_hErrThread, PIPE_OUTPUT_THREAD_TIMEOUT ) != WAIT_OBJECT_0)
152+ if (WaitForSingleObject (m_hErrThread, m_terminationTimeoutMs ) != WAIT_OBJECT_0)
135153 {
136154 // If the thread is still running, we need kill it first before exit to avoid AV
137155 if (!LOG_LAST_ERROR_IF (GetExitCodeThread (m_hErrThread, &dwThreadStatus) == 0 ) &&
0 commit comments