1- #include <ws2tcpip .h>
1+ #include <winsock .h>
22
33#pragma comment( lib, "kernel32.lib")
44#pragma comment( lib, "ws2_32.lib")
5- #pragma warning( disable: 4701 )
65
76__forceinline void memzero ( void * mem , size_t size ) // anti memset
87{
9- do
10- {
11- ( (volatile char * )mem )[-- size ] = 0 ;
12- }
13- while ( size );
8+ while ( size -- )
9+ ( (volatile char * )mem )[size ] = 0 ;
1410}
1511
1612#define MAX_SPAWN_HANDLES MAXIMUM_WAIT_OBJECTS
1713
18- __forceinline void spawner ( char * app , unsigned port , unsigned cgis )
1914// based on spawn-fcgi-win32.c
2015// found here: http://redmine.lighttpd.net/boards/2/topics/686#message-689
16+ __forceinline void spawner ( char * app , unsigned port , unsigned cgis ,
17+ unsigned restart_delay )
2118{
2219 SOCKET s ;
2320
@@ -52,7 +49,7 @@ __forceinline void spawner( char * app, unsigned port, unsigned cgis )
5249 return ;
5350 }
5451
55- if ( -1 == bind ( s , (struct sockaddr * )& fcgi_addr_in ,
52+ if ( -1 == bind ( s , ( struct sockaddr * )& fcgi_addr_in ,
5653 sizeof ( fcgi_addr_in ) ) )
5754 return ;
5855 }
@@ -64,13 +61,17 @@ __forceinline void spawner( char * app, unsigned port, unsigned cgis )
6461 if ( !SetProcessShutdownParameters ( 0x380 , SHUTDOWN_NORETRY ) )
6562 return ;
6663
64+ // php-cgis crash silently if restart delay is 1 second or more
65+ // (https://github.com/deemru/php-cgi-spawner/issues/3)
66+ if ( restart_delay >= 1000 )
67+ SetErrorMode ( SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX );
68+
6769 {
6870 HANDLE hProcesses [MAX_SPAWN_HANDLES ];
6971 PROCESS_INFORMATION pi ;
7072 STARTUPINFOA si ;
7173 unsigned i ;
7274
73- memzero ( hProcesses , sizeof ( hProcesses ) );
7475 memzero ( & si , sizeof ( si ) );
7576
7677 si .cb = sizeof ( STARTUPINFO );
@@ -79,49 +80,47 @@ __forceinline void spawner( char * app, unsigned port, unsigned cgis )
7980 si .hStdError = INVALID_HANDLE_VALUE ;
8081 si .hStdInput = (HANDLE )s ;
8182
83+ for ( i = 0 ; i < cgis ; i ++ )
84+ hProcesses [i ] = INVALID_HANDLE_VALUE ;
85+
8286 for ( ;; )
8387 {
84- BOOL isSpawnNeed = FALSE;
85-
8688 for ( i = 0 ; i < cgis ; i ++ )
8789 {
88- if ( hProcesses [i ] != NULL )
90+ if ( hProcesses [i ] == INVALID_HANDLE_VALUE )
8991 {
90- DWORD dwExitCode ;
91- if ( !GetExitCodeProcess ( hProcesses [i ], & dwExitCode ) )
92+ if ( !CreateProcessA ( NULL , app , NULL , NULL , TRUE,
93+ CREATE_NO_WINDOW , NULL , NULL ,
94+ & si , & pi ) )
9295 return ;
9396
94- if ( dwExitCode != STILL_ACTIVE )
95- {
96- CloseHandle ( hProcesses [i ] );
97- hProcesses [i ] = NULL ;
98- isSpawnNeed = TRUE;
99- }
100- }
101- else
102- {
103- isSpawnNeed = TRUE;
97+ CloseHandle ( pi .hThread );
98+ hProcesses [i ] = pi .hProcess ;
10499 }
105100 }
106101
107- if ( isSpawnNeed )
102+ WaitForMultipleObjects ( cgis , & hProcesses [0 ], FALSE, INFINITE );
103+
104+ for ( i = 0 ; i < cgis ; i ++ )
108105 {
109- for ( i = 0 ; i < cgis ; i ++ )
106+ if ( hProcesses [ i ] != INVALID_HANDLE_VALUE )
110107 {
111- if ( hProcesses [i ] == NULL )
112- {
113- if ( !CreateProcessA ( NULL , app , NULL , NULL , TRUE,
114- CREATE_NO_WINDOW , NULL , NULL ,
115- & si , & pi ) )
116- return ;
108+ DWORD dwExitCode ;
109+ if ( !GetExitCodeProcess ( hProcesses [i ], & dwExitCode ) )
110+ return ;
117111
118- CloseHandle ( pi .hThread );
119- hProcesses [i ] = pi .hProcess ;
112+ if ( dwExitCode != STILL_ACTIVE )
113+ {
114+ CloseHandle ( hProcesses [i ] );
115+ hProcesses [i ] = INVALID_HANDLE_VALUE ;
120116 }
121117 }
122118 }
123119
124- WaitForMultipleObjects ( cgis , & hProcesses [0 ], FALSE, INFINITE );
120+ // optional restart delay
121+ // (https://github.com/deemru/php-cgi-spawner/issues/3)
122+ if ( restart_delay )
123+ Sleep ( restart_delay );
125124 }
126125 }
127126}
@@ -210,14 +209,19 @@ __forceinline unsigned getargs( char * cmd, char ** argv, unsigned max )
210209 return argc ;
211210}
212211
213- #define ARGS_COUNT 4
212+ #define ARGS_MAX 5
213+ #define ARGS_MIN 4
214214
215215void __cdecl WinMainCRTStartup ()
216216{
217- char * argv [ARGS_COUNT ];
217+ char * argv [ARGS_MAX ];
218+ argv [4 ] = NULL ;
218219
219- if ( ARGS_COUNT == getargs ( GetCommandLineA (), (char * * )& argv , ARGS_COUNT ) )
220- spawner ( argv [1 ], char2num ( argv [2 ] ), char2num ( argv [3 ] ) );
220+ if ( ARGS_MIN <= getargs ( GetCommandLineA (), (char * * )& argv , ARGS_MAX ) )
221+ {
222+ spawner ( argv [1 ], char2num ( argv [2 ] ), char2num ( argv [3 ] ),
223+ argv [4 ] ? char2num ( argv [4 ] ) : 0 );
224+ }
221225
222226 ExitProcess ( 0 );
223227}
0 commit comments