]> granicus.if.org Git - php/commitdiff
- Fixed bug #62033 (php-fpm exits with status 0 on some failures to start)
authorJerome Loyet <fat@php.net>
Fri, 25 May 2012 19:13:57 +0000 (21:13 +0200)
committerJerome Loyet <fat@php.net>
Fri, 25 May 2012 19:13:57 +0000 (21:13 +0200)
NEWS
sapi/fpm/config.m4
sapi/fpm/fpm/fpm.c
sapi/fpm/fpm/fpm.h
sapi/fpm/fpm/fpm_children.c
sapi/fpm/fpm/fpm_main.c
sapi/fpm/fpm/fpm_process_ctl.c
sapi/fpm/fpm/fpm_signals.c
sapi/fpm/fpm/fpm_signals.h
sapi/fpm/fpm/fpm_unix.c

diff --git a/NEWS b/NEWS
index ac4eeb5934e90a5fce6c2553247d459791b5c387..3da506fb4320312482faffd57c1921174f74280d 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -61,6 +61,8 @@ PHP                                                                        NEWS
     for non-root start). (fat)
   . Fixed bug #61839 (Unable to cross-compile PHP with --enable-fpm). (fat)
   . Fixed bug #61026 (FPM pools can listen on the same address). (fat)
+  . Fixed bug #62033 (php-fpm exits with status 0 on some failures to start).
+    (fat)
 
 - Intl
   . ResourceBundle constructor now accepts NULL for the first two arguments.
index 6c860c9a22199c72c30ff472119f3b01411ee59d..ad46717acdb1eaace8fa93125c1b6174ca42ba05 100644 (file)
@@ -16,6 +16,7 @@ AC_DEFUN([AC_FPM_STDLIBS],
   AC_CHECK_HEADERS([errno.h fcntl.h stdio.h stdlib.h unistd.h sys/uio.h])
   AC_CHECK_HEADERS([sys/select.h sys/socket.h sys/time.h])
   AC_CHECK_HEADERS([arpa/inet.h netinet/in.h])
+  AC_CHECK_HEADERS([sysexits.h])
 ])
 
 AC_DEFUN([AC_FPM_PRCTL],
index 909902b71c5b41293069acac1ace9d11d6527b55..176dbaf32ec874ce66a4042eff93d19007ab3c48 100644 (file)
@@ -66,7 +66,7 @@ int fpm_init(int argc, char **argv, char *config, char *prefix, char *pid, int t
            0 > fpm_event_init_main()) {
 
                if (fpm_globals.test_successful) {
-                       exit(0);
+                       exit(FPM_EXIT_OK);
                } else {
                        zlog(ZLOG_ERROR, "FPM initialization failed");
                        return -1;
index 2a69cb229f9d40affc38b1a6be7b40eaab56e277..b0bed0a07415a7585377b987e9abfdbcbd7bae46 100644 (file)
@@ -7,6 +7,35 @@
 
 #include <unistd.h>
 
+#ifdef HAVE_SYSEXITS_H
+#include <sysexits.h>
+#endif
+
+#ifdef EX_OK
+#define FPM_EXIT_OK EX_OK
+#else
+#define FPM_EXIT_OK 0
+#endif
+
+#ifdef EX_USAGE
+#define FPM_EXIT_USAGE EX_USAGE
+#else
+#define FPM_EXIT_USAGE 64
+#endif
+
+#ifdef EX_SOFTWARE
+#define FPM_EXIT_SOFTWARE EX_SOFTWARE
+#else
+#define FPM_EXIT_SOFTWARE 70
+#endif
+
+#ifdef EX_CONFIG
+#define FPM_EXIT_CONFIG EX_CONFIG
+#else
+#define FPM_EXIT_CONFIG 78
+#endif
+
+
 int fpm_run(int *max_requests);
 int fpm_init(int argc, char **argv, char *config, char *prefix, char *pid, int test_conf, int run_as_root);
 
index 35058b0ea10ca9fba5577e8bc26bb2f88617df73..84a94743322157c912ad1226f0a6ba81e9dc846d 100644 (file)
@@ -156,7 +156,7 @@ static void fpm_child_init(struct fpm_worker_pool_s *wp) /* {{{ */
            0 > fpm_php_init_child(wp)) {
 
                zlog(ZLOG_ERROR, "[pool %s] child failed to initialize", wp->config->name);
-               exit(255);
+               exit(FPM_EXIT_SOFTWARE);
        }
 }
 /* }}} */
@@ -198,7 +198,7 @@ void fpm_children_bury() /* {{{ */
                                restart_child = 0;
                        }
 
-                       if (WEXITSTATUS(status) != 0) {
+                       if (WEXITSTATUS(status) != FPM_EXIT_OK) {
                                severity = ZLOG_WARNING;
                        }
 
index 130673f331bf83aaf602bb64cede79f7dcb13fd9..c3fd2bca74cf53af1e0b7617a351052421a3bc49 100644 (file)
@@ -1528,7 +1528,7 @@ static zend_module_entry cgi_module_entry = {
  */
 int main(int argc, char *argv[])
 {
-       int exit_status = SUCCESS;
+       int exit_status = FPM_EXIT_OK;
        int cgi = 0, c, use_extended_info = 0;
        zend_file_handle file_handle;
 
@@ -1659,7 +1659,7 @@ int main(int argc, char *argv[])
                                php_output_end_all(TSRMLS_C);
                                php_output_deactivate(TSRMLS_C);
                                fcgi_shutdown();
-                               exit_status = 0;
+                               exit_status = FPM_EXIT_OK;
                                goto out;
 
                        case 'i': /* php info & quit */
@@ -1680,7 +1680,7 @@ int main(int argc, char *argv[])
                                php_output_end_all(TSRMLS_C);
                                php_output_deactivate(TSRMLS_C);
                                fcgi_shutdown();
-                               exit_status = 0;
+                               exit_status = (c == 'h') ? FPM_EXIT_OK : FPM_EXIT_USAGE;
                                goto out;
 
                        case 'v': /* show php version & quit */
@@ -1688,7 +1688,7 @@ int main(int argc, char *argv[])
                                if (php_request_startup(TSRMLS_C) == FAILURE) {
                                        SG(server_context) = NULL;
                                        php_module_shutdown(TSRMLS_C);
-                                       return FAILURE;
+                                       return FPM_EXIT_SOFTWARE;
                                }
                                SG(headers_sent) = 1;
                                SG(request_info).no_headers = 1;
@@ -1700,7 +1700,7 @@ int main(int argc, char *argv[])
 #endif
                                php_request_shutdown((void *) 0);
                                fcgi_shutdown();
-                               exit_status = 0;
+                               exit_status = FPM_EXIT_OK;
                                goto out;
                }
        }
@@ -1711,14 +1711,14 @@ int main(int argc, char *argv[])
                if (php_request_startup(TSRMLS_C) == FAILURE) {
                        SG(server_context) = NULL;
                        php_module_shutdown(TSRMLS_C);
-                       return FAILURE;
+                       return FPM_EXIT_SOFTWARE;
                }
                SG(headers_sent) = 1;
                SG(request_info).no_headers = 1;
                php_print_info(0xFFFFFFFF TSRMLS_CC);
                php_request_shutdown((void *) 0);
                fcgi_shutdown();
-               exit_status = 0;
+               exit_status = FPM_EXIT_OK;
                goto out;
        }
 
@@ -1731,7 +1731,7 @@ int main(int argc, char *argv[])
                php_output_end_all(TSRMLS_C);
                php_output_deactivate(TSRMLS_C);
                fcgi_shutdown();
-               exit_status = 0;
+               exit_status = FPM_EXIT_USAGE;
                goto out;
        }
 
@@ -1750,7 +1750,7 @@ int main(int argc, char *argv[])
 #ifdef ZTS
                tsrm_shutdown();
 #endif
-               return FAILURE;
+               return FPM_EXIT_SOFTWARE;
        }
        
        if (use_extended_info) {
@@ -1793,14 +1793,23 @@ consult the installation file that came with this distribution, or visit \n\
                         */
                        tsrm_shutdown();
 #endif
-                       return FAILURE;
+                       return FPM_EXIT_SOFTWARE;
                }
        }
 
        if (0 > fpm_init(argc, argv, fpm_config ? fpm_config : CGIG(fpm_config), fpm_prefix, fpm_pid, test_conf, php_allow_to_run_as_root)) {
-               return FAILURE;
+
+               if (fpm_global_config.daemonize) {
+                       zlog(ZLOG_DEBUG, "Sending SIGUSR2 (error) to parent %d", getppid());
+                       kill(getppid(), SIGUSR2);
+               }
+               return FPM_EXIT_CONFIG;
        }
 
+       if (fpm_global_config.daemonize) {
+               zlog(ZLOG_DEBUG, "Sending SIGUSR1 (OK) to parent %d", getppid());
+               kill(getppid(), SIGUSR1);
+       }
        fpm_is_running = 1;
 
        fcgi_fd = fpm_run(&max_requests);
@@ -1832,7 +1841,7 @@ consult the installation file that came with this distribution, or visit \n\
                                fcgi_finish_request(&request, 1);
                                SG(server_context) = NULL;
                                php_module_shutdown(TSRMLS_C);
-                               return FAILURE;
+                               return FPM_EXIT_SOFTWARE;
                        }
 
                        /* check if request_method has been sent.
@@ -1920,17 +1929,9 @@ fastcgi_request_done:
 
                        php_request_shutdown((void *) 0);
 
-                       if (exit_status == 0) {
-                               exit_status = EG(exit_status);
-                       }
-
                        requests++;
                        if (max_requests && (requests == max_requests)) {
                                fcgi_finish_request(&request, 1);
-                               if (max_requests != 1) {
-                                       /* no need to return exit_status of the last request */
-                                       exit_status = 0;
-                               }
                                break;
                        }
                        /* end of fastcgi loop */
@@ -1944,7 +1945,7 @@ fastcgi_request_done:
                        free(cgi_sapi_module.ini_entries);
                }
        } zend_catch {
-               exit_status = 255;
+               exit_status = FPM_EXIT_SOFTWARE;
        } zend_end_try();
 
 out:
index e698eb0ca2a8495917afa939cbe8cf135d6b8f10..7840d17f8b9c58b68f4610012b29033d37d576ae 100644 (file)
@@ -71,7 +71,7 @@ static void fpm_pctl_exit() /* {{{ */
 
        fpm_conf_unlink_pid();
        fpm_cleanups_run(FPM_CLEANUP_PARENT_EXIT_MAIN);
-       exit(0);
+       exit(FPM_EXIT_OK);
 }
 /* }}} */
 
@@ -100,7 +100,7 @@ static void fpm_pctl_exec() /* {{{ */
        fpm_cleanups_run(FPM_CLEANUP_PARENT_EXEC);
        execvp(saved_argv[0], saved_argv);
        zlog(ZLOG_SYSERROR, "failed to reload: execvp() failed");
-       exit(1);
+       exit(FPM_EXIT_SOFTWARE);
 }
 /* }}} */
 
index 8993a860ae87d4ac375e42e955ba4ed8925a0100..656269f1a3610cf162ba8a5ac213965d446ff320 100644 (file)
@@ -249,3 +249,15 @@ int fpm_signals_get_fd() /* {{{ */
 }
 /* }}} */
 
+void fpm_signals_sighandler_exit_ok(pid_t pid) /* {{{ */
+{
+       exit(FPM_EXIT_OK);
+}
+/* }}} */
+
+void fpm_signals_sighandler_exit_config(pid_t pid) /* {{{ */
+{
+       exit(FPM_EXIT_CONFIG);
+}
+/* }}} */
+
index eb80faecfdb54bb0fa999d31ade039d3d3c659a7..13484cbac281ffe9fb08701799735cc60db50478 100644 (file)
@@ -11,6 +11,9 @@ int fpm_signals_init_main();
 int fpm_signals_init_child();
 int fpm_signals_get_fd();
 
+void fpm_signals_sighandler_exit_ok(pid_t pid);
+void fpm_signals_sighandler_exit_config(pid_t pid);
+
 extern const char *fpm_signal_names[NSIG + 1];
 
 #endif
index fb61d63416d6567904d33eeee15b684434798c8f..1ab81896054df780578b52f3b28f90570389611d 100644 (file)
@@ -23,6 +23,7 @@
 #include "fpm_clock.h"
 #include "fpm_stdio.h"
 #include "fpm_unix.h"
+#include "fpm_signals.h"
 #include "zlog.h"
 
 size_t fpm_pagesize;
@@ -242,18 +243,75 @@ int fpm_unix_init_main() /* {{{ */
 
        fpm_pagesize = getpagesize();
        if (fpm_global_config.daemonize) {
-               switch (fork()) {
-                       case -1 :
+               /*
+                * If daemonize, the calling process will die soon
+                * and the master process continues to initialize itself.
+                *
+                * The parent process has then to wait for the master
+                * process to initialize to return a consistent exit
+                * value. For this pupose, the master process will
+                * send USR1 if everything went well and USR2
+                * otherwise.
+                */
+
+               struct sigaction act;
+               struct sigaction oldact_usr1;
+               struct sigaction oldact_usr2;
+               struct timeval tv;
+
+               /*
+                * set sigaction for USR1 before fork
+                * save old sigaction to restore it after
+                * fork in the child process (the master process)
+                */
+               memset(&act, 0, sizeof(act));
+               memset(&act, 0, sizeof(oldact_usr1));
+               act.sa_handler = fpm_signals_sighandler_exit_ok;
+               sigfillset(&act.sa_mask);
+               sigaction(SIGUSR1, &act, &oldact_usr1);
+
+               /*
+                * set sigaction for USR2 before fork
+                * save old sigaction to restore it after
+                * fork in the child process (the master process)
+                */
+               memset(&act, 0, sizeof(act));
+               memset(&act, 0, sizeof(oldact_usr2));
+               act.sa_handler = fpm_signals_sighandler_exit_config;
+               sigfillset(&act.sa_mask);
+               sigaction(SIGUSR2, &act, &oldact_usr2);
+
+               /* then fork */
+               pid_t pid = fork();
+               switch (pid) {
+
+                       case -1 : /* error */
                                zlog(ZLOG_SYSERROR, "failed to daemonize");
                                return -1;
-                       case 0 :
+
+                       case 0 : /* children */
+                               /* restore USR1 and USR2 sigaction */
+                               sigaction(SIGUSR1, &oldact_usr1, NULL);
+                               sigaction(SIGUSR2, &oldact_usr2, NULL);
                                break;
-                       default :
+
+                       default : /* parent */
                                fpm_cleanups_run(FPM_CLEANUP_PARENT_EXIT);
-                               exit(0);
+
+                               /*
+                                * wait for 10s before exiting with error
+                                * the child is supposed to send USR1 or USR2 to tell the parent
+                                * how it goes for it
+                                */
+                               tv.tv_sec = 10;
+                               tv.tv_usec = 0;
+                               zlog(ZLOG_DEBUG, "The calling process is waiting for the master process to ping");
+                               select(0, NULL, NULL, NULL, &tv);
+                               exit(FPM_EXIT_SOFTWARE);
                }
        }
 
+       /* continue as a child */
        setsid();
        if (0 > fpm_clock_init()) {
                return -1;