197 lines
5.0 KiB
C++
197 lines
5.0 KiB
C++
// Copyright (c) .NET Foundation. All rights reserved.
|
|
// Licensed under the MIT License. See License.txt in the project root for license information.
|
|
|
|
#pragma once
|
|
|
|
#define ONE_MINUTE_IN_MILLISECONDS 60000
|
|
class SERVER_PROCESS;
|
|
|
|
class PROCESS_MANAGER
|
|
{
|
|
public:
|
|
|
|
virtual
|
|
~PROCESS_MANAGER();
|
|
|
|
VOID
|
|
ReferenceProcessManager() const
|
|
{
|
|
InterlockedIncrement(&m_cRefs);
|
|
}
|
|
|
|
VOID
|
|
DereferenceProcessManager() const
|
|
{
|
|
if (InterlockedDecrement(&m_cRefs) == 0)
|
|
{
|
|
delete this;
|
|
}
|
|
}
|
|
|
|
HRESULT
|
|
GetProcess(
|
|
_In_ REQUESTHANDLER_CONFIG *pConfig,
|
|
_In_ BOOL fWebsocketEnabled,
|
|
_Out_ SERVER_PROCESS **ppServerProcess
|
|
);
|
|
|
|
HANDLE
|
|
QueryNULHandle()
|
|
{
|
|
return m_hNULHandle;
|
|
}
|
|
|
|
HRESULT
|
|
Initialize(
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
SendShutdownSignal()
|
|
{
|
|
AcquireSRWLockExclusive( &m_srwLock );
|
|
|
|
for(DWORD i = 0; i < m_dwProcessesPerApplication; ++i )
|
|
{
|
|
if( m_ppServerProcessList != NULL &&
|
|
m_ppServerProcessList[i] != NULL )
|
|
{
|
|
m_ppServerProcessList[i]->SendSignal();
|
|
m_ppServerProcessList[i]->DereferenceServerProcess();
|
|
m_ppServerProcessList[i] = NULL;
|
|
}
|
|
}
|
|
|
|
ReleaseSRWLockExclusive( &m_srwLock );
|
|
}
|
|
|
|
VOID
|
|
ShutdownProcess(
|
|
SERVER_PROCESS* pServerProcess
|
|
)
|
|
{
|
|
AcquireSRWLockExclusive( &m_srwLock );
|
|
|
|
ShutdownProcessNoLock( pServerProcess );
|
|
|
|
ReleaseSRWLockExclusive( &m_srwLock );
|
|
}
|
|
|
|
VOID
|
|
ShutdownAllProcesses(
|
|
)
|
|
{
|
|
AcquireSRWLockExclusive( &m_srwLock );
|
|
|
|
ShutdownAllProcessesNoLock();
|
|
|
|
ReleaseSRWLockExclusive( &m_srwLock );
|
|
}
|
|
|
|
VOID
|
|
IncrementRapidFailCount(
|
|
VOID
|
|
)
|
|
{
|
|
InterlockedIncrement(&m_cRapidFailCount);
|
|
}
|
|
|
|
PROCESS_MANAGER() :
|
|
m_ppServerProcessList( NULL ),
|
|
m_hNULHandle( NULL ),
|
|
m_cRapidFailCount( 0 ),
|
|
m_dwProcessesPerApplication( 1 ),
|
|
m_dwRouteToProcessIndex( 0 ),
|
|
m_fServerProcessListReady(FALSE),
|
|
m_cRefs( 1 )
|
|
{
|
|
m_ppServerProcessList = NULL;
|
|
m_fServerProcessListReady = FALSE;
|
|
InitializeSRWLock( &m_srwLock );
|
|
}
|
|
|
|
private:
|
|
|
|
BOOL
|
|
RapidFailsPerMinuteExceeded(
|
|
LONG dwRapidFailsPerMinute
|
|
)
|
|
{
|
|
DWORD dwCurrentTickCount = GetTickCount();
|
|
|
|
if( (dwCurrentTickCount - m_dwRapidFailTickStart)
|
|
>= ONE_MINUTE_IN_MILLISECONDS )
|
|
{
|
|
//
|
|
// reset counters every minute.
|
|
//
|
|
|
|
InterlockedExchange(&m_cRapidFailCount, 0);
|
|
m_dwRapidFailTickStart = dwCurrentTickCount;
|
|
}
|
|
|
|
return m_cRapidFailCount > dwRapidFailsPerMinute;
|
|
}
|
|
|
|
VOID
|
|
ShutdownProcessNoLock(
|
|
SERVER_PROCESS* pServerProcess
|
|
)
|
|
{
|
|
for(DWORD i = 0; i < m_dwProcessesPerApplication; ++i )
|
|
{
|
|
if( m_ppServerProcessList != NULL &&
|
|
m_ppServerProcessList[i] != NULL &&
|
|
m_ppServerProcessList[i]->GetPort() == pServerProcess->GetPort() )
|
|
{
|
|
// shutdown pServerProcess if not already shutdown.
|
|
m_ppServerProcessList[i]->StopProcess();
|
|
m_ppServerProcessList[i]->DereferenceServerProcess();
|
|
m_ppServerProcessList[i] = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
VOID
|
|
ShutdownAllProcessesNoLock(
|
|
VOID
|
|
)
|
|
{
|
|
for(DWORD i = 0; i < m_dwProcessesPerApplication; ++i )
|
|
{
|
|
if( m_ppServerProcessList != NULL &&
|
|
m_ppServerProcessList[i] != NULL )
|
|
{
|
|
// shutdown pServerProcess if not already shutdown.
|
|
m_ppServerProcessList[i]->SendSignal();
|
|
m_ppServerProcessList[i]->DereferenceServerProcess();
|
|
m_ppServerProcessList[i] = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
volatile LONG m_cRapidFailCount;
|
|
DWORD m_dwRapidFailTickStart;
|
|
DWORD m_dwProcessesPerApplication;
|
|
volatile DWORD m_dwRouteToProcessIndex;
|
|
|
|
SRWLOCK m_srwLock;
|
|
SERVER_PROCESS **m_ppServerProcessList;
|
|
|
|
//
|
|
// m_hNULHandle is used to redirect stdout/stderr to NUL.
|
|
// If Createprocess is called to launch a batch file for example,
|
|
// it tries to write to the console buffer by default. It fails to
|
|
// start if the console buffer is owned by the parent process i.e
|
|
// in our case w3wp.exe. So we have to redirect the stdout/stderr
|
|
// of the child process to NUL or to a file (anything other than
|
|
// the console buffer of the parent process).
|
|
//
|
|
|
|
HANDLE m_hNULHandle;
|
|
mutable LONG m_cRefs;
|
|
|
|
volatile static BOOL sm_fWSAStartupDone;
|
|
volatile BOOL m_fServerProcessListReady;
|
|
};
|