]> granicus.if.org Git - php/commitdiff
Basic implementation for FCGI to respect PHP_FCGI_CHILDREN on Windows
authorAnatol Belski <ab@php.net>
Wed, 13 Jan 2016 10:53:29 +0000 (11:53 +0100)
committerAnatol Belski <ab@php.net>
Wed, 13 Jan 2016 20:32:36 +0000 (21:32 +0100)
PHP_FCGI_CHILDREN number of children processes will be spawned, sharing
same TCP socket. To implement yet

- children cleanup on exit
- automatic children re-spawning

sapi/cgi/cgi_main.c

index c1cca1e3d21556874c010d7ab3cabec77abc8c8c..eec97fe686b2a72e87034118973dfd19fa60868f 100644 (file)
@@ -102,7 +102,6 @@ struct sigaction act, old_term, old_quit, old_int;
 
 static void (*php_php_import_environment_variables)(zval *array_ptr);
 
-#ifndef PHP_WIN32
 /* these globals used for forking children on unix systems */
 /**
  * Number of child processes that will get created to service requests
@@ -115,6 +114,7 @@ static int children = 0;
  */
 static int parent = 1;
 
+#ifndef PHP_WIN32
 /* Did parent received exit signals SIG_TERM/SIG_INT/SIG_QUIT */
 static int exit_signal = 0;
 
@@ -354,9 +354,7 @@ static void sapi_fcgi_flush(void *server_context)
        fcgi_request *request = (fcgi_request*) server_context;
 
        if (
-#ifndef PHP_WIN32
                !parent &&
-#endif
                request && !fcgi_flush(request, 0)) {
 
                php_handle_aborted_connection();
@@ -900,9 +898,7 @@ static int sapi_cgi_deactivate(void)
        if (SG(sapi_started)) {
                if (fcgi_is_fastcgi()) {
                        if (
-#ifndef PHP_WIN32
                                !parent &&
-#endif
                                !fcgi_finish_request((fcgi_request*)SG(server_context), 0)) {
                                php_handle_aborted_connection();
                        }
@@ -1979,8 +1975,7 @@ consult the installation file that came with this distribution, or visit \n\
                /* library is already initialized, now init our request */
                request = fcgi_init_request(fcgi_fd, NULL, NULL, NULL);
 
-#ifndef PHP_WIN32
-               /* Pre-fork, if required */
+               /* Pre-fork or spawn, if required */
                if (getenv("PHP_FCGI_CHILDREN")) {
                        char * children_str = getenv("PHP_FCGI_CHILDREN");
                        children = atoi(children_str);
@@ -1996,6 +1991,7 @@ consult the installation file that came with this distribution, or visit \n\
                        fcgi_set_mgmt_var("FCGI_MAX_REQS",  sizeof("FCGI_MAX_REQS")-1,  "1", sizeof("1")-1);
                }
 
+#ifndef PHP_WIN32
                if (children) {
                        int running = 0;
                        pid_t pid;
@@ -2081,6 +2077,77 @@ consult the installation file that came with this distribution, or visit \n\
                        parent = 0;
                }
 
+#else
+               if (children) {
+                       char *cmd_line;
+                       HANDLE kid_cgi_ps[64];
+                       int kids = children < 64 ? children : 64;
+                       char kid_buf[16];
+                       char my_name[MAX_PATH] = {0};
+
+                       SetEnvironmentVariable("PHP_FCGI_CHILDREN", NULL); /* kids will inherit the env, don't let them spawn */
+
+                       GetModuleFileName(NULL, my_name, MAX_PATH);
+                       cmd_line = my_name;
+
+                       while (0 < kids--) {
+                               PROCESS_INFORMATION pi;
+                               STARTUPINFO si;
+
+                               ZeroMemory(&si, sizeof(si));
+                               si.cb = sizeof(si);
+                               ZeroMemory(&pi, sizeof(pi));
+
+                               si.dwFlags = STARTF_USESTDHANDLES;
+                               si.hStdOutput = INVALID_HANDLE_VALUE;
+                               si.hStdInput  = (HANDLE)_get_osfhandle(fcgi_fd);
+                               si.hStdError  = INVALID_HANDLE_VALUE;
+
+                               if (CreateProcess(NULL, cmd_line, NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi)) {
+                                       kid_cgi_ps[kids] = pi.hProcess;
+                                       CloseHandle(pi.hThread);
+                               } else {
+                                       DWORD err = GetLastError();
+                                       char *err_text;
+
+                                       kid_cgi_ps[kids] = INVALID_HANDLE_VALUE;
+
+                                       (void)FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ARGUMENT_ARRAY,
+                                               NULL,
+                                               err,
+                                               LANG_NEUTRAL,
+                                               (LPTSTR)&err_text,
+                                               0,
+                                               NULL);
+                                       
+                                       fprintf(stderr, "unable to spawn: [0x%08lx]: %s\n", err, err_text);
+                               }
+                       }
+                       
+                       snprintf(kid_buf, 16, "%d", children);
+                       SetEnvironmentVariable("PHP_FCGI_CHILDREN", kid_buf); /* restore my env */
+
+                       kids = children < 64 ? children : 64;
+                       WaitForMultipleObjects(kids, kid_cgi_ps, FALSE, INFINITE);
+
+                       while (0 < kids--) {
+                               DWORD status;
+
+                               if (INVALID_HANDLE_VALUE == kid_cgi_ps[kids]) {
+                                       if(!GetExitCodeProcess(kid_cgi_ps[kids], &status)) {
+                                               continue;
+                                       }
+
+                                       if(status != STILL_ACTIVE){
+                                               CloseHandle(kid_cgi_ps[kids]);
+                                               kid_cgi_ps[kids] = INVALID_HANDLE_VALUE;
+                                       }
+                               }
+                       }
+                       goto parent_out;
+               } else {
+                       parent = 0;
+               }
 #endif /* WIN32 */
        }
 
@@ -2584,9 +2651,7 @@ out:
 #endif
        }
 
-#ifndef PHP_WIN32
 parent_out:
-#endif
 
        SG(server_context) = NULL;
        php_module_shutdown();