Skip to content

Commit

Permalink
fix #275: refactor graceful recycling logic to avoid deadlock potential
Browse files Browse the repository at this point in the history
  • Loading branch information
tjanczuk committed May 3, 2013
1 parent a3f0db9 commit 58c2898
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 4 deletions.
13 changes: 12 additions & 1 deletion src/iisnode/cnodeapplication.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

CNodeApplication::CNodeApplication(CNodeApplicationManager* applicationManager, BOOL isDebugger, NodeDebugCommand debugCommand, DWORD debugPort)
: applicationManager(applicationManager), scriptName(NULL), processManager(NULL),
isDebugger(isDebugger), peerApplication(NULL), debugCommand(debugCommand), debugPort(debugPort)
isDebugger(isDebugger), peerApplication(NULL), debugCommand(debugCommand), debugPort(debugPort), needsRecycling(FALSE)
{
}

Expand Down Expand Up @@ -146,3 +146,14 @@ DWORD CNodeApplication::GetProcessCount()
{
return this->processManager->GetProcessCount();
}

void CNodeApplication::SetNeedsRecycling()
{
this->needsRecycling = TRUE;
}

BOOL CNodeApplication::GetNeedsRecycling()
{
return this->needsRecycling;
}

3 changes: 3 additions & 0 deletions src/iisnode/cnodeapplication.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ class CNodeApplication
BOOL isDebugger;
NodeDebugCommand debugCommand;
DWORD debugPort;
BOOL needsRecycling;

void Cleanup();

Expand All @@ -39,6 +40,8 @@ class CNodeApplication
DWORD GetDebugPort();
DWORD GetActiveRequestCount();
DWORD GetProcessCount();
void SetNeedsRecycling();
BOOL GetNeedsRecycling();
};

#endif
12 changes: 9 additions & 3 deletions src/iisnode/cnodeapplicationmanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ HRESULT CNodeApplicationManager::Dispatch(IHttpContext* context, IHttpEventProvi
ENTER_SRW_SHARED(this->srwlock)

CheckError(this->GetOrCreateNodeApplication(context, debugCommand, FALSE, &application));
if (application)
if (application && !application->GetNeedsRecycling())
{
// this is the sweetspot code path: application already exists, shared read lock is sufficient

Expand All @@ -202,14 +202,20 @@ HRESULT CNodeApplicationManager::Dispatch(IHttpContext* context, IHttpEventProvi

LEAVE_SRW_SHARED(this->srwlock)

if (!application)
if (!application || application->GetNeedsRecycling())
{
// this is the initialization code path for activating request:
// application must be created which requires an exclusive lock

ENTER_SRW_EXCLUSIVE(this->srwlock)

CheckError(this->GetOrCreateNodeApplication(context, debugCommand, TRUE, &application));
if (application->GetNeedsRecycling())
{
this->RecycleApplicationAssumeLock(application);
CheckError(this->GetOrCreateNodeApplication(context, debugCommand, TRUE, &application));
}

CheckError(application->Dispatch(context, pProvider, ctx));

LEAVE_SRW_EXCLUSIVE(this->srwlock)
Expand Down Expand Up @@ -339,7 +345,7 @@ HRESULT CNodeApplicationManager::RecycleApplicationAssumeLock(CNodeApplication*

void CNodeApplicationManager::OnScriptModified(CNodeApplicationManager* manager, CNodeApplication* application)
{
manager->RecycleApplication(application);
application->SetNeedsRecycling();
}

// this method is always called under exclusive this->srwlock
Expand Down

0 comments on commit 58c2898

Please sign in to comment.