@@ -5,7 +5,7 @@ CNodeApplicationManager::CNodeApplicationManager(IHttpServer* server, HTTP_MODUL
55 : server(server), moduleId(moduleId), applications(NULL ), asyncManager(NULL ), jobObject(NULL ),
66 breakAwayFromJobObject(FALSE ), fileWatcher(NULL ), initialized(FALSE ), eventProvider(NULL ),
77 currentDebugPort(0 ), inspector(NULL ), totalRequests(0 ), controlSignalHandlerThread(NULL ),
8- signalPipe(NULL ), signalPipeName(NULL ), pPipeSecAttr(NULL )
8+ signalPipe(NULL ), signalPipeName(NULL ), pPipeSecAttr(NULL ), _fSignalPipeInitialized( FALSE )
99{
1010 InitializeSRWLock (&this ->srwlock );
1111}
@@ -90,13 +90,95 @@ CNodeApplicationManager::GetPipeSecurityAttributes(
9090 return this ->pPipeSecAttr ;
9191}
9292
93+ HRESULT CNodeApplicationManager::InitializeControlPipe ()
94+ {
95+ HRESULT hr = S_OK;
96+ UUID uuid;
97+ RPC_WSTR suuid = NULL ;
98+
99+ if ( _fSignalPipeInitialized )
100+ {
101+ return hr;
102+ }
103+
104+ //
105+ // generate unique pipe name
106+ //
107+
108+ ErrorIf (RPC_S_OK != UuidCreate (&uuid), ERROR_CAN_NOT_COMPLETE);
109+ ErrorIf (RPC_S_OK != UuidToStringW (&uuid, &suuid), ERROR_NOT_ENOUGH_MEMORY);
110+ ErrorIf ((this ->signalPipeName = new WCHAR[1024 ]) == NULL , ERROR_NOT_ENOUGH_MEMORY);
111+ wcscpy (this ->signalPipeName , L" \\\\ .\\ pipe\\ " );
112+ wcscpy (this ->signalPipeName + 9 , (WCHAR*)suuid);
113+ RpcStringFreeW (&suuid);
114+ suuid = NULL ;
115+
116+ this ->signalPipe = CreateNamedPipeW ( this ->signalPipeName ,
117+ PIPE_ACCESS_INBOUND,
118+ PIPE_TYPE_MESSAGE | PIPE_WAIT,
119+ 1 ,
120+ MAX_BUFFER_SIZE,
121+ MAX_BUFFER_SIZE,
122+ 0 ,
123+ GetPipeSecurityAttributes () );
124+
125+ ErrorIf ( this ->signalPipe == INVALID_HANDLE_VALUE,
126+ HRESULT_FROM_WIN32 (ERROR_INVALID_HANDLE) );
127+
128+ //
129+ // start pipe reader thread.
130+ //
131+
132+ this ->controlSignalHandlerThread = (HANDLE) _beginthreadex ( NULL ,
133+ 0 ,
134+ CNodeApplicationManager::ControlSignalHandler,
135+ this ,
136+ 0 ,
137+ NULL );
138+
139+ ErrorIf ((HANDLE)-1L == this ->controlSignalHandlerThread , ERROR_NOT_ENOUGH_MEMORY);
140+
141+ this ->GetEventProvider ()->Log (L" iisnode initialized control pipe" , WINEVENT_LEVEL_INFO);
142+
143+ _fSignalPipeInitialized = TRUE ;
144+
145+ Error:
146+
147+ if (suuid != NULL )
148+ {
149+ RpcStringFreeW (&suuid);
150+ suuid = NULL ;
151+ }
152+
153+ if ( FAILED ( hr ) )
154+ {
155+ if (NULL != this ->controlSignalHandlerThread )
156+ {
157+ CloseHandle (this ->controlSignalHandlerThread );
158+ this ->controlSignalHandlerThread = NULL ;
159+ }
160+
161+ if (NULL != this ->signalPipe )
162+ {
163+ CloseHandle (this ->signalPipe );
164+ this ->signalPipe = NULL ;
165+ }
166+
167+ if (NULL != this ->signalPipeName )
168+ {
169+ delete[] this ->signalPipeName ;
170+ this ->signalPipeName = NULL ;
171+ }
172+ }
173+
174+ return hr;
175+ }
176+
93177HRESULT CNodeApplicationManager::InitializeCore (IHttpContext* context)
94178{
95179 HRESULT hr;
96180 BOOL isInJob, createJob;
97181 JOBOBJECT_EXTENDED_LIMIT_INFORMATION jobInfo;
98- UUID uuid;
99- RPC_WSTR suuid = NULL ;
100182
101183 ErrorIf (NULL == (this ->eventProvider = new CNodeEventProvider ()), ERROR_NOT_ENOUGH_MEMORY);
102184 CheckError (this ->eventProvider ->Initialize ());
@@ -150,62 +232,19 @@ HRESULT CNodeApplicationManager::InitializeCore(IHttpContext* context)
150232 HRESULT_FROM_WIN32 (GetLastError ()));
151233 }
152234
153- if (CModuleConfiguration::GetRecycleSignalEnabled (context))
235+ if (CModuleConfiguration::GetRecycleSignalEnabled (context) && !_fSignalPipeInitialized )
154236 {
155- //
156- // generate unique pipe name
157- //
158-
159- ErrorIf (RPC_S_OK != UuidCreate (&uuid), ERROR_CAN_NOT_COMPLETE);
160- ErrorIf (RPC_S_OK != UuidToStringW (&uuid, &suuid), ERROR_NOT_ENOUGH_MEMORY);
161- ErrorIf ((this ->signalPipeName = new WCHAR[1024 ]) == NULL , ERROR_NOT_ENOUGH_MEMORY);
162- wcscpy (this ->signalPipeName , L" \\\\ .\\ pipe\\ " );
163- wcscpy (this ->signalPipeName + 9 , (WCHAR*)suuid);
164- RpcStringFreeW (&suuid);
165- suuid = NULL ;
166-
167- this ->signalPipe = CreateNamedPipeW ( this ->signalPipeName ,
168- PIPE_ACCESS_INBOUND,
169- PIPE_TYPE_MESSAGE | PIPE_WAIT,
170- 1 ,
171- MAX_BUFFER_SIZE,
172- MAX_BUFFER_SIZE,
173- 0 ,
174- GetPipeSecurityAttributes () );
175-
176- ErrorIf ( this ->signalPipe == INVALID_HANDLE_VALUE,
177- HRESULT_FROM_WIN32 (ERROR_INVALID_HANDLE) );
178-
179- //
180- // start pipe reader thread.
181- //
182-
183- this ->controlSignalHandlerThread = (HANDLE) _beginthreadex ( NULL ,
184- 0 ,
185- CNodeApplicationManager::ControlSignalHandler,
186- this ,
187- 0 ,
188- NULL );
189-
190- ErrorIf ((HANDLE)-1L == this ->controlSignalHandlerThread , ERROR_NOT_ENOUGH_MEMORY);
191-
192- this ->GetEventProvider ()->Log (L" iisnode initialized control pipe" , WINEVENT_LEVEL_INFO);
237+ CheckError (InitializeControlPipe ());
193238 }
194239
195240 this ->initialized = TRUE ;
196241
197- this ->GetEventProvider ()->Log (L" iisnode initialized the application manager" , WINEVENT_LEVEL_INFO);
242+ this ->GetEventProvider ()->Log (context, L" iisnode initialized the application manager" , WINEVENT_LEVEL_INFO);
198243
199244 return S_OK;
200245Error:
201246
202- this ->GetEventProvider ()->Log (L" iisnode failed to initialize the application manager" , WINEVENT_LEVEL_ERROR);
203-
204- if (suuid != NULL )
205- {
206- RpcStringFreeW (&suuid);
207- suuid = NULL ;
208- }
247+ this ->GetEventProvider ()->Log (context, L" iisnode failed to initialize the application manager" , WINEVENT_LEVEL_ERROR);
209248
210249 if (NULL != this ->asyncManager )
211250 {
@@ -230,6 +269,8 @@ HRESULT CNodeApplicationManager::InitializeCore(IHttpContext* context)
230269
231270CNodeApplicationManager::~CNodeApplicationManager ()
232271{
272+ HANDLE hPipe = NULL ;
273+
233274 while (NULL != this ->applications )
234275 {
235276 delete this ->applications ->nodeApplication ;
@@ -238,6 +279,30 @@ CNodeApplicationManager::~CNodeApplicationManager()
238279 delete current;
239280 }
240281
282+ if ( _fSignalPipeInitialized )
283+ {
284+ //
285+ // try to connect to the pipe to unblock the thread
286+ // waiting on ConnectNamedPipe
287+ // We dont need to check any errors on whether the connect
288+ // succeeded because we dont care.
289+ //
290+
291+ hPipe = CreateFileW ( this ->GetSignalPipeName (),
292+ GENERIC_WRITE,
293+ 0 ,
294+ NULL ,
295+ OPEN_EXISTING,
296+ 0 ,
297+ NULL );
298+
299+ if (hPipe != NULL )
300+ {
301+ CloseHandle (hPipe);
302+ hPipe = NULL ;
303+ }
304+ }
305+
241306 if (NULL != this ->controlSignalHandlerThread )
242307 {
243308 CloseHandle (this ->controlSignalHandlerThread );
@@ -304,7 +369,7 @@ CAsyncManager* CNodeApplicationManager::GetAsyncManager()
304369
305370HRESULT CNodeApplicationManager::Dispatch (IHttpContext* context, IHttpEventProvider* pProvider, CNodeHttpStoredContext** ctx)
306371{
307- HRESULT hr;
372+ HRESULT hr = S_OK ;
308373 CNodeApplication* application;
309374 NodeDebugCommand debugCommand;
310375
@@ -319,6 +384,18 @@ HRESULT CNodeApplicationManager::Dispatch(IHttpContext* context, IHttpEventProvi
319384 {
320385 default :
321386
387+ if (CModuleConfiguration::GetRecycleSignalEnabled (context) && !_fSignalPipeInitialized)
388+ {
389+ ENTER_SRW_EXCLUSIVE (this ->srwlock )
390+
391+ if (CModuleConfiguration::GetRecycleSignalEnabled (context) && !_fSignalPipeInitialized)
392+ {
393+ CheckError (InitializeControlPipe ());
394+ }
395+
396+ LEAVE_SRW_EXCLUSIVE (this ->srwlock )
397+ }
398+
322399 ENTER_SRW_SHARED (this ->srwlock )
323400
324401 CheckError (this ->GetOrCreateNodeApplication (context, debugCommand, FALSE , &application));
@@ -554,7 +631,7 @@ HRESULT CNodeApplicationManager::GetOrCreateNodeApplicationCore(PCWSTR physicalP
554631 }
555632 else
556633 {
557- this ->GetEventProvider ()->Log (L" iisnode found an existing node.js application to dispatch the http request to" , WINEVENT_LEVEL_VERBOSE);
634+ this ->GetEventProvider ()->Log (context, L" iisnode found an existing node.js application to dispatch the http request to" , WINEVENT_LEVEL_VERBOSE);
558635 }
559636
560637 return S_OK;
@@ -569,7 +646,7 @@ HRESULT CNodeApplicationManager::GetOrCreateNodeApplicationCore(PCWSTR physicalP
569646 delete applicationEntry;
570647 }
571648
572- this ->GetEventProvider ()->Log (L" iisnode failed to create a new node.js application" , WINEVENT_LEVEL_ERROR);
649+ this ->GetEventProvider ()->Log (context, L" iisnode failed to create a new node.js application" , WINEVENT_LEVEL_ERROR);
573650
574651 return hr;
575652}
@@ -860,7 +937,7 @@ HRESULT CNodeApplicationManager::GetOrCreateDebuggedNodeApplicationCore(PCWSTR p
860937 }
861938 else
862939 {
863- this ->GetEventProvider ()->Log (L" iisnode found an existing node.js debugger to dispatch the http request to" , WINEVENT_LEVEL_VERBOSE);
940+ this ->GetEventProvider ()->Log (context, L" iisnode found an existing node.js debugger to dispatch the http request to" , WINEVENT_LEVEL_VERBOSE);
864941 }
865942
866943 return S_OK;
@@ -884,7 +961,7 @@ HRESULT CNodeApplicationManager::GetOrCreateDebuggedNodeApplicationCore(PCWSTR p
884961 delete debuggerEntry;
885962 }
886963
887- this ->GetEventProvider ()->Log (L" iisnode failed to create a new node.js application to debug or the debugger for that application" , WINEVENT_LEVEL_ERROR);
964+ this ->GetEventProvider ()->Log (context, L" iisnode failed to create a new node.js application to debug or the debugger for that application" , WINEVENT_LEVEL_ERROR);
888965
889966 return hr;
890967}
0 commit comments