Skip to content

Commit

Permalink
fix w3wp crashes
Browse files Browse the repository at this point in the history
  • Loading branch information
rramachand21-zz committed Feb 19, 2017
1 parent b3058d6 commit 8f9d43a
Show file tree
Hide file tree
Showing 21 changed files with 405 additions and 149 deletions.
3 changes: 2 additions & 1 deletion src/config/iisnode_dev_x64.xml
Expand Up @@ -32,7 +32,7 @@ Details at http://learn.iis.net/page.aspx/241/configuration-extensibility/
<attribute name="nodeProcessCountPerApplication" type="uint" defaultValue="1"/>
<attribute name="nodeProcessCommandLine" type="string" expanded="true" defaultValue="node.exe"/>
<attribute name="interceptor" type="string" expanded="true" defaultValue="&quot;%programfiles(x86)%\iisnode-dev\release\x64\interceptor.js&quot;" />
<attribute name="maxConcurrentRequestsPerProcess" type="uint" allowInfitnite="true" defaultValue="1024"/>
<attribute name="maxConcurrentRequestsPerProcess" type="uint" allowInfinite="true" defaultValue="1024"/>
<attribute name="maxNamedPipeConnectionRetry" type="uint" defaultValue="100"/>
<attribute name="namedPipeConnectionRetryDelay" type="uint" defaultValue="250"/>
<attribute name="maxNamedPipeConnectionPoolSize" type="uint" defaultValue="512"/>
Expand Down Expand Up @@ -60,5 +60,6 @@ Details at http://learn.iis.net/page.aspx/241/configuration-extensibility/
<attribute name="configOverrides" type="string" expanded="true" defaultValue="iisnode.yml"/>
<attribute name="recycleSignalEnabled" type="bool" defaultValue="false"/>
<attribute name="idlePageOutTimePeriod" type="uint" defaultValue="0" /> <!-- disabled with default value 0 -->
<attribute name="nodeProcessStickySessions" type="bool" defaultValue="false"/>
</sectionSchema>
</configSchema>
3 changes: 2 additions & 1 deletion src/config/iisnode_dev_x86_on_x64.xml
Expand Up @@ -32,7 +32,7 @@ Details at http://learn.iis.net/page.aspx/241/configuration-extensibility/
<attribute name="nodeProcessCountPerApplication" type="uint" defaultValue="1"/>
<attribute name="nodeProcessCommandLine" type="string" expanded="true" defaultValue="node.exe"/>
<attribute name="interceptor" type="string" expanded="true" defaultValue="&quot;%programfiles(x86)%\iisnode-dev\release\x86\interceptor.js&quot;" />
<attribute name="maxConcurrentRequestsPerProcess" type="uint" allowInfitnite="true" defaultValue="1024"/>
<attribute name="maxConcurrentRequestsPerProcess" type="uint" allowInfinite="true" defaultValue="1024"/>
<attribute name="maxNamedPipeConnectionRetry" type="uint" defaultValue="100"/>
<attribute name="namedPipeConnectionRetryDelay" type="uint" defaultValue="250"/>
<attribute name="maxNamedPipeConnectionPoolSize" type="uint" defaultValue="512"/>
Expand Down Expand Up @@ -60,5 +60,6 @@ Details at http://learn.iis.net/page.aspx/241/configuration-extensibility/
<attribute name="configOverrides" type="string" expanded="true" defaultValue="iisnode.yml"/>
<attribute name="recycleSignalEnabled" type="bool" defaultValue="false"/>
<attribute name="idlePageOutTimePeriod" type="uint" defaultValue="0" /> <!-- disabled with default value 0 -->
<attribute name="nodeProcessStickySessions" type="bool" defaultValue="false"/>
</sectionSchema>
</configSchema>
3 changes: 2 additions & 1 deletion src/config/iisnode_dev_x86_on_x86.xml
Expand Up @@ -32,7 +32,7 @@ Details at http://learn.iis.net/page.aspx/241/configuration-extensibility/
<attribute name="nodeProcessCountPerApplication" type="uint" defaultValue="1"/>
<attribute name="nodeProcessCommandLine" type="string" expanded="true" defaultValue="node.exe"/>
<attribute name="interceptor" type="string" expanded="true" defaultValue="&quot;%programfiles%\iisnode-dev\release\x86\interceptor.js&quot;" />
<attribute name="maxConcurrentRequestsPerProcess" type="uint" allowInfitnite="true" defaultValue="1024"/>
<attribute name="maxConcurrentRequestsPerProcess" type="uint" allowInfinite="true" defaultValue="1024"/>
<attribute name="maxNamedPipeConnectionRetry" type="uint" defaultValue="100"/>
<attribute name="namedPipeConnectionRetryDelay" type="uint" defaultValue="250"/>
<attribute name="maxNamedPipeConnectionPoolSize" type="uint" defaultValue="512"/>
Expand Down Expand Up @@ -60,5 +60,6 @@ Details at http://learn.iis.net/page.aspx/241/configuration-extensibility/
<attribute name="configOverrides" type="string" expanded="true" defaultValue="iisnode.yml"/>
<attribute name="recycleSignalEnabled" type="bool" defaultValue="false"/>
<attribute name="idlePageOutTimePeriod" type="uint" defaultValue="0" /> <!-- disabled with default value 0 -->
<attribute name="nodeProcessStickySessions" type="bool" defaultValue="false"/>
</sectionSchema>
</configSchema>
3 changes: 2 additions & 1 deletion src/config/iisnode_express_schema.xml
Expand Up @@ -32,7 +32,7 @@ Details at http://learn.iis.net/page.aspx/241/configuration-extensibility/
<attribute name="nodeProcessCountPerApplication" type="uint" defaultValue="1"/>
<attribute name="nodeProcessCommandLine" type="string" expanded="true" defaultValue="node.exe"/>
<attribute name="interceptor" type="string" expanded="true" defaultValue="&quot;%programfiles%\iisnode-express\interceptor.js&quot;" />
<attribute name="maxConcurrentRequestsPerProcess" type="uint" allowInfitnite="true" defaultValue="1024"/>
<attribute name="maxConcurrentRequestsPerProcess" type="uint" allowInfinite="true" defaultValue="1024"/>
<attribute name="maxNamedPipeConnectionRetry" type="uint" defaultValue="100"/>
<attribute name="namedPipeConnectionRetryDelay" type="uint" defaultValue="250"/>
<attribute name="maxNamedPipeConnectionPoolSize" type="uint" defaultValue="512"/>
Expand Down Expand Up @@ -60,5 +60,6 @@ Details at http://learn.iis.net/page.aspx/241/configuration-extensibility/
<attribute name="configOverrides" type="string" expanded="true" defaultValue="iisnode.yml"/>
<attribute name="recycleSignalEnabled" type="bool" defaultValue="false"/>
<attribute name="idlePageOutTimePeriod" type="uint" defaultValue="0" /> <!-- disabled with default value 0 -->
<attribute name="nodeProcessStickySessions" type="bool" defaultValue="false"/>
</sectionSchema>
</configSchema>
3 changes: 2 additions & 1 deletion src/config/iisnode_express_schema_x64.xml
Expand Up @@ -32,7 +32,7 @@ Details at http://learn.iis.net/page.aspx/241/configuration-extensibility/
<attribute name="nodeProcessCountPerApplication" type="uint" defaultValue="1"/>
<attribute name="nodeProcessCommandLine" type="string" expanded="true" defaultValue="node.exe"/>
<attribute name="interceptor" type="string" expanded="true" defaultValue="&quot;%programfiles(x86)%\iisnode-express\interceptor.js&quot;" />
<attribute name="maxConcurrentRequestsPerProcess" type="uint" allowInfitnite="true" defaultValue="1024"/>
<attribute name="maxConcurrentRequestsPerProcess" type="uint" allowInfinite="true" defaultValue="1024"/>
<attribute name="maxNamedPipeConnectionRetry" type="uint" defaultValue="100"/>
<attribute name="namedPipeConnectionRetryDelay" type="uint" defaultValue="250"/>
<attribute name="maxNamedPipeConnectionPoolSize" type="uint" defaultValue="512"/>
Expand Down Expand Up @@ -60,5 +60,6 @@ Details at http://learn.iis.net/page.aspx/241/configuration-extensibility/
<attribute name="configOverrides" type="string" expanded="true" defaultValue="iisnode.yml"/>
<attribute name="recycleSignalEnabled" type="bool" defaultValue="false"/>
<attribute name="idlePageOutTimePeriod" type="uint" defaultValue="0" /> <!-- disabled with default value 0 -->
<attribute name="nodeProcessStickySessions" type="bool" defaultValue="false"/>
</sectionSchema>
</configSchema>
3 changes: 2 additions & 1 deletion src/config/iisnode_schema.xml
Expand Up @@ -32,7 +32,7 @@ Details at http://learn.iis.net/page.aspx/241/configuration-extensibility/
<attribute name="nodeProcessCountPerApplication" type="uint" defaultValue="1"/>
<attribute name="nodeProcessCommandLine" type="string" expanded="true" defaultValue="node.exe"/>
<attribute name="interceptor" type="string" expanded="true" defaultValue="&quot;%programfiles%\iisnode\interceptor.js&quot;" />
<attribute name="maxConcurrentRequestsPerProcess" type="uint" allowInfitnite="true" defaultValue="1024"/>
<attribute name="maxConcurrentRequestsPerProcess" type="uint" allowInfinite="true" defaultValue="1024"/>
<attribute name="maxNamedPipeConnectionRetry" type="uint" defaultValue="100"/>
<attribute name="namedPipeConnectionRetryDelay" type="uint" defaultValue="250"/>
<attribute name="maxNamedPipeConnectionPoolSize" type="uint" defaultValue="512"/>
Expand Down Expand Up @@ -60,5 +60,6 @@ Details at http://learn.iis.net/page.aspx/241/configuration-extensibility/
<attribute name="configOverrides" type="string" expanded="true" defaultValue="iisnode.yml"/>
<attribute name="recycleSignalEnabled" type="bool" defaultValue="false"/>
<attribute name="idlePageOutTimePeriod" type="uint" defaultValue="0" /> <!-- disabled with default value 0 -->
<attribute name="nodeProcessStickySessions" type="bool" defaultValue="false"/>
</sectionSchema>
</configSchema>
3 changes: 2 additions & 1 deletion src/config/iisnode_schema_x64.xml
Expand Up @@ -32,7 +32,7 @@ Details at http://learn.iis.net/page.aspx/241/configuration-extensibility/
<attribute name="nodeProcessCountPerApplication" type="uint" defaultValue="1"/>
<attribute name="nodeProcessCommandLine" type="string" expanded="true" defaultValue="node.exe"/>
<attribute name="interceptor" type="string" expanded="true" defaultValue="&quot;%programfiles%\iisnode\interceptor.js&quot;" />
<attribute name="maxConcurrentRequestsPerProcess" type="uint" allowInfitnite="true" defaultValue="1024"/>
<attribute name="maxConcurrentRequestsPerProcess" type="uint" allowInfinite="true" defaultValue="1024"/>
<attribute name="maxNamedPipeConnectionRetry" type="uint" defaultValue="100"/>
<attribute name="namedPipeConnectionRetryDelay" type="uint" defaultValue="250"/>
<attribute name="maxNamedPipeConnectionPoolSize" type="uint" defaultValue="512"/>
Expand Down Expand Up @@ -60,5 +60,6 @@ Details at http://learn.iis.net/page.aspx/241/configuration-extensibility/
<attribute name="configOverrides" type="string" expanded="true" defaultValue="iisnode.yml"/>
<attribute name="recycleSignalEnabled" type="bool" defaultValue="false"/>
<attribute name="idlePageOutTimePeriod" type="uint" defaultValue="0" /> <!-- disabled with default value 0 -->
<attribute name="nodeProcessStickySessions" type="bool" defaultValue="false"/>
</sectionSchema>
</configSchema>
33 changes: 26 additions & 7 deletions src/iisnode/casyncmanager.cpp
Expand Up @@ -4,14 +4,15 @@ extern RtlNtStatusToDosError pRtlNtStatusToDosError;

void ASYNC_CONTEXT::RunSynchronousContinuations()
{
while (this->continueSynchronously)
BOOL fCompletionPosted = FALSE;
while (!fCompletionPosted && this->continueSynchronously)
{
// The continueSynchronously is used to unwind the call stack
// to avoid stack overflow in case of a synchronous IO completions
this->continueSynchronously = FALSE;
DWORD bytesCompleteted = this->bytesCompleteted;
this->bytesCompleteted = 0;
this->completionProcessor(S_OK, bytesCompleteted, (LPOVERLAPPED)this);
this->completionProcessor(S_OK, bytesCompleteted, (LPOVERLAPPED)this, &fCompletionPosted);
}
}

Expand Down Expand Up @@ -171,19 +172,31 @@ unsigned int WINAPI CAsyncManager::Worker(void* arg)
{
OVERLAPPED_ENTRY* entry = entries;
for (int i = 0; i < entriesRemoved; i++)
{
{
BOOL fCompletionPosted = FALSE;

if (0L == entry->lpCompletionKey
&& NULL != (ctx = (ASYNC_CONTEXT*)entry->lpOverlapped)
&& NULL != ctx->completionProcessor) // regular IO completion - invoke custom processor
{

error = (entry->lpOverlapped->Internal == STATUS_SUCCESS) ? ERROR_SUCCESS
: pRtlNtStatusToDosError(entry->lpOverlapped->Internal);
ctx = (ASYNC_CONTEXT*)entry->lpOverlapped;

ctx->completionProcessor(
(0 == entry->dwNumberOfBytesTransferred && ERROR_SUCCESS == error) ? ERROR_NO_DATA : error,
entry->dwNumberOfBytesTransferred,
(LPOVERLAPPED)ctx);
ctx->RunSynchronousContinuations();
(LPOVERLAPPED)ctx,
&fCompletionPosted);

if(!fCompletionPosted)
{
ctx->RunSynchronousContinuations();
}

CNodeHttpStoredContext* storedCtx = (CNodeHttpStoredContext*)ctx->data;
storedCtx->DereferenceNodeHttpStoredContext();
}
else if (-1L == entry->lpCompletionKey) // shutdown initiated from Terminate
{
Expand All @@ -194,8 +207,14 @@ unsigned int WINAPI CAsyncManager::Worker(void* arg)
if (-2L == entry->lpCompletionKey) // completion of an alertable wait state timer initialized from OnTimer
{
ctx = (ASYNC_CONTEXT*)entry->lpOverlapped;
ctx->completionProcessor(S_OK, 0, (LPOVERLAPPED)ctx);
ctx->RunSynchronousContinuations();
ctx->completionProcessor(S_OK, 0, (LPOVERLAPPED)ctx, &fCompletionPosted);
if(!fCompletionPosted)
{
ctx->RunSynchronousContinuations();
}

CNodeHttpStoredContext* storedCtx = (CNodeHttpStoredContext*)ctx->data;
storedCtx->DereferenceNodeHttpStoredContext();
}
else if (-3L == entry->lpCompletionKey) // continuation initiated form PostContinuation
{
Expand Down
11 changes: 10 additions & 1 deletion src/iisnode/casyncmanager.h
@@ -1,9 +1,18 @@
#ifndef __CASYNCMANAGER_H__
#define __CASYNCMANAGER_H__

typedef
VOID
(WINAPI *LPOVERLAPPED_COMPLETION_ROUTINE_IISNODE)(
_In_ DWORD dwErrorCode,
_In_ DWORD dwNumberOfBytesTransfered,
_Inout_ LPOVERLAPPED lpOverlapped,
_Inout_ BOOL * fCompletionPosted
);

typedef struct {
OVERLAPPED overlapped; // this member must be first in the struct
LPOVERLAPPED_COMPLETION_ROUTINE completionProcessor;
LPOVERLAPPED_COMPLETION_ROUTINE_IISNODE completionProcessor;
BOOL continueSynchronously;
void* data;
HANDLE timer;
Expand Down
22 changes: 19 additions & 3 deletions src/iisnode/cmoduleconfiguration.cpp
Expand Up @@ -87,15 +87,21 @@ CModuleConfiguration::~CModuleConfiguration()
this->debuggerPathSegment = NULL;
}

if( NULL != this->debugPortRange )
{
delete [] this->debugPortRange;
this->debugPortRange = NULL;
}

if (NULL != this->node_env)
{
delete this->node_env;
delete [] this->node_env;
this->node_env = NULL;
}

if (NULL != this->watchedFiles)
{
delete this->watchedFiles;
delete [] this->watchedFiles;
this->watchedFiles = NULL;
}

Expand Down Expand Up @@ -814,6 +820,10 @@ HRESULT CModuleConfiguration::ApplyConfigOverrideKeyValue(IHttpContext* context,
{
CheckError(GetDWORD(valueStart, &config->maxLogFiles));
}
else if (0 == strcmpi(keyStart, "nodeProcessStickySessions"))
{
CheckError(GetBOOL(valueStart, &config->nodeProcessStickySessions));
}
else if (0 == strcmpi(keyStart, "loggingEnabled"))
{
CheckError(GetBOOL(valueStart, &config->loggingEnabled));
Expand Down Expand Up @@ -1228,6 +1238,7 @@ HRESULT CModuleConfiguration::GetConfig(IHttpContext* context, CModuleConfigurat
CheckError(GetDWORD(section, L"maxTotalLogFileSizeInKB", &c->maxTotalLogFileSizeInKB));
CheckError(GetDWORD(section, L"maxLogFileSizeInKB", &c->maxLogFileSizeInKB));
CheckError(GetDWORD(section, L"maxLogFiles", &c->maxLogFiles));
CheckError(GetBOOL(section, L"nodeProcessStickySessions", &c->nodeProcessStickySessions, FALSE));
CheckError(GetBOOL(section, L"loggingEnabled", &c->loggingEnabled, TRUE));
CheckError(GetBOOL(section, L"devErrorsEnabled", &c->devErrorsEnabled, TRUE));
CheckError(GetBOOL(section, L"flushResponse", &c->flushResponse, FALSE));
Expand All @@ -1236,7 +1247,7 @@ HRESULT CModuleConfiguration::GetConfig(IHttpContext* context, CModuleConfigurat
CheckError(GetString(section, L"debuggerExtensionDll", &c->debuggerExtensionDll));
CheckError(GetBOOL(section, L"debugHeaderEnabled", &c->debugHeaderEnabled, FALSE));
CheckError(GetBOOL(section, L"recycleSignalEnabled", &c->recycleSignalEnabled, FALSE));
CheckError(GetString(section, L"debuggerVirtualDir", &c->debuggerVirtualDir));
CheckError(GetString(section, L"debuggerVirtualDir", &c->debuggerVirtualDir));
c->debuggerVirtualDirLength = wcslen(c->debuggerVirtualDir);
CheckError(GetString(section, L"node_env", &c->node_env));
CheckError(GetString(section, L"debuggerPortRange", &c->debugPortRange));
Expand Down Expand Up @@ -1433,6 +1444,11 @@ BOOL CModuleConfiguration::GetDebuggingEnabled(IHttpContext* ctx)
GETCONFIG(debuggingEnabled)
}

BOOL CModuleConfiguration::GetProcessStickySessions(IHttpContext* ctx)
{
GETCONFIG(nodeProcessStickySessions)
}

PWSTR CModuleConfiguration::GetDebuggerExtensionDll(IHttpContext* ctx)
{
GETCONFIG(debuggerExtensionDll)
Expand Down
2 changes: 2 additions & 0 deletions src/iisnode/cmoduleconfiguration.h
Expand Up @@ -52,6 +52,7 @@ class CModuleConfiguration : public IHttpStoredContext
static BOOL invalid;
SRWLOCK srwlock;
LPWSTR configOverrides;
BOOL nodeProcessStickySessions;

static IHttpServer* server;
static HTTP_MODULE_ID moduleId;
Expand Down Expand Up @@ -129,6 +130,7 @@ class CModuleConfiguration : public IHttpStoredContext
static BOOL GetEnableXFF(IHttpContext* ctx);
static HRESULT GetPromoteServerVars(IHttpContext* ctx, char*** vars, int* count);
static LPWSTR GetConfigOverrides(IHttpContext* ctx);
static BOOL GetProcessStickySessions(IHttpContext* ctx);

static HRESULT CreateNodeEnvironment(IHttpContext* ctx, DWORD debugPort, PCH namedPipe, PCH signalPipeName, PCH* env);

Expand Down
4 changes: 4 additions & 0 deletions src/iisnode/cnodeeventprovider.cpp
Expand Up @@ -107,10 +107,14 @@ HRESULT CNodeEventProvider::Log(IHttpContext *context, PCWSTR message, UCHAR lev
}
}

/*
commented because there might be a race condition after calling PostCompletion and then using the IHttpContext object.
Uncomment this only after making sure there is no race condition. (IHttpContext cannot be used after calling PostCompletion)
if( IsEnabled( context->GetTraceContext(), level ) )
{
CheckError( RaiseEvent( context->GetTraceContext(), message, level, activityId ) );
}
*/

return S_OK;
Error:
Expand Down
6 changes: 5 additions & 1 deletion src/iisnode/cnodehttpmodule.cpp
Expand Up @@ -219,7 +219,9 @@ REQUEST_NOTIFICATION_STATUS CNodeHttpModule::OnAsyncCompletion(
bytesCompleted = async->bytesCompleteted;
async->bytesCompleteted = 0;
}
async->completionProcessor(pCompletionInfo->GetCompletionStatus(), bytesCompleted, ctx->GetOverlapped());
BOOL fCompletionPosted = FALSE;
async->completionProcessor(pCompletionInfo->GetCompletionStatus(), bytesCompleted, ctx->GetOverlapped(), &fCompletionPosted);

async->RunSynchronousContinuations();
}

Expand Down Expand Up @@ -266,6 +268,8 @@ REQUEST_NOTIFICATION_STATUS CNodeHttpModule::OnAsyncCompletion(
break;
};

ctx->DereferenceNodeHttpStoredContext();

return result;
}

Expand Down
6 changes: 3 additions & 3 deletions src/iisnode/cnodehttpstoredcontext.cpp
Expand Up @@ -6,7 +6,7 @@ CNodeHttpStoredContext::CNodeHttpStoredContext(CNodeApplication* nodeApplication
requestNotificationStatus(RQ_NOTIFICATION_PENDING), connectionRetryCount(0), pendingAsyncOperationCount(1),
targetUrl(NULL), targetUrlLength(0), childContext(NULL), isConnectionFromPool(FALSE), expectResponseBody(TRUE),
closeConnection(FALSE), isUpgrade(FALSE), upgradeContext(NULL), opaqueFlagSet(FALSE), requestPumpStarted(FALSE),
responseChunkBufferSize(0)
responseChunkBufferSize(0), m_cRefs(1)
{
IHttpTraceContext* tctx;
LPCGUID pguid;
Expand Down Expand Up @@ -75,7 +75,7 @@ CNodeApplication* CNodeHttpStoredContext::GetNodeApplication()
return this->nodeApplication;
}

void CNodeHttpStoredContext::SetNextProcessor(LPOVERLAPPED_COMPLETION_ROUTINE processor)
void CNodeHttpStoredContext::SetNextProcessor(LPOVERLAPPED_COMPLETION_ROUTINE_IISNODE processor)
{
this->asyncContext.completionProcessor = processor;
this->SetContinueSynchronously(FALSE);
Expand All @@ -95,7 +95,7 @@ LPOVERLAPPED CNodeHttpStoredContext::InitializeOverlapped()

void CNodeHttpStoredContext::CleanupStoredContext()
{
delete this;
DereferenceNodeHttpStoredContext();
}

CNodeProcess* CNodeHttpStoredContext::GetNodeProcess()
Expand Down

0 comments on commit 8f9d43a

Please sign in to comment.