php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Return to Bug #62033
Patch bug62033-v2.patch revision 2012-05-25 08:48 UTC by fat@php.net
Patch bug62033.patch revision 2012-05-23 22:50 UTC by fat@php.net

Patch bug62033-v2.patch for FPM related Bug #62033

Patch version 2012-05-25 08:48 UTC

Return to Bug #62033 | Download this patch
This patch renders other patches obsolete

Obsolete patches:

Patch Revisions:

Developer: fat@php.net

diff --git a/sapi/fpm/config.m4 b/sapi/fpm/config.m4
index 953fa1f..c23485a 100644
--- a/sapi/fpm/config.m4
+++ b/sapi/fpm/config.m4
@@ -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],
diff --git a/sapi/fpm/fpm/fpm.c b/sapi/fpm/fpm/fpm.c
index 909902b..176dbaf 100644
--- a/sapi/fpm/fpm/fpm.c
+++ b/sapi/fpm/fpm/fpm.c
@@ -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;
diff --git a/sapi/fpm/fpm/fpm.h b/sapi/fpm/fpm/fpm.h
index 2a69cb2..b0bed0a 100644
--- a/sapi/fpm/fpm/fpm.h
+++ b/sapi/fpm/fpm/fpm.h
@@ -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);
 
diff --git a/sapi/fpm/fpm/fpm_children.c b/sapi/fpm/fpm/fpm_children.c
index 35058b0..84a9474 100644
--- a/sapi/fpm/fpm/fpm_children.c
+++ b/sapi/fpm/fpm/fpm_children.c
@@ -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;
 			}
 
diff --git a/sapi/fpm/fpm/fpm_main.c b/sapi/fpm/fpm/fpm_main.c
index 95a7623..08477da 100644
--- a/sapi/fpm/fpm/fpm_main.c
+++ b/sapi/fpm/fpm/fpm_main.c
@@ -1538,7 +1538,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;
 	zend_file_handle file_handle;
 
@@ -1668,7 +1668,7 @@ int main(int argc, char *argv[])
 				php_printf("\n");
 				php_end_ob_buffers(1 TSRMLS_CC);
 				fcgi_shutdown();
-				exit_status = 0;
+				exit_status = FPM_EXIT_OK;
 				goto out;
 
 			case 'i': /* php info & quit */
@@ -1689,7 +1689,7 @@ int main(int argc, char *argv[])
 				php_cgi_usage(argv[0]);
 				php_end_ob_buffers(1 TSRMLS_CC);
 				fcgi_shutdown();
-				exit_status = 0;
+				exit_status = (c == 'h') ? FPM_EXIT_OK : FPM_EXIT_USAGE;
 				goto out;
 
 			case 'v': /* show php version & quit */
@@ -1697,7 +1697,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;
@@ -1709,7 +1709,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;
 		}
 	}
@@ -1720,14 +1720,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;
 	}
 
@@ -1739,7 +1739,7 @@ int main(int argc, char *argv[])
 		SG(headers_sent) = 1;
 		php_cgi_usage(argv[0]);
 		php_end_ob_buffers(1 TSRMLS_CC);
-		exit_status = 0;
+		exit_status = FPM_EXIT_USAGE;
 		fcgi_shutdown();
 		goto out;
 	}
@@ -1759,7 +1759,7 @@ int main(int argc, char *argv[])
 #ifdef ZTS
 		tsrm_shutdown();
 #endif
-		return FAILURE;
+		return FPM_EXIT_SOFTWARE;
 	}
 
 	/* check force_cgi after startup, so we have proper output */
@@ -1798,14 +1798,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);
@@ -1837,7 +1846,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.
@@ -1925,17 +1934,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 */
@@ -1949,7 +1950,7 @@ fastcgi_request_done:
 			free(cgi_sapi_module.ini_entries);
 		}
 	} zend_catch {
-		exit_status = 255;
+		exit_status = FPM_EXIT_SOFTWARE;
 	} zend_end_try();
 
 out:
diff --git a/sapi/fpm/fpm/fpm_process_ctl.c b/sapi/fpm/fpm/fpm_process_ctl.c
index e698eb0..7840d17 100644
--- a/sapi/fpm/fpm/fpm_process_ctl.c
+++ b/sapi/fpm/fpm/fpm_process_ctl.c
@@ -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);
 }
 /* }}} */
 
diff --git a/sapi/fpm/fpm/fpm_signals.c b/sapi/fpm/fpm/fpm_signals.c
index 8993a86..656269f 100644
--- a/sapi/fpm/fpm/fpm_signals.c
+++ b/sapi/fpm/fpm/fpm_signals.c
@@ -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);
+}
+/* }}} */
+
diff --git a/sapi/fpm/fpm/fpm_signals.h b/sapi/fpm/fpm/fpm_signals.h
index eb80fae..13484cb 100644
--- a/sapi/fpm/fpm/fpm_signals.h
+++ b/sapi/fpm/fpm/fpm_signals.h
@@ -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
diff --git a/sapi/fpm/fpm/fpm_unix.c b/sapi/fpm/fpm/fpm_unix.c
index fb61d63..1ab8189 100644
--- a/sapi/fpm/fpm/fpm_unix.c
+++ b/sapi/fpm/fpm/fpm_unix.c
@@ -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;
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Tue Mar 19 10:01:30 2024 UTC