summaryrefslogtreecommitdiff
path: root/sapi/cli
diff options
context:
space:
mode:
authorJoe Watkins <krakjoe@php.net>2019-06-27 15:09:58 +0200
committerJoe Watkins <krakjoe@php.net>2019-06-29 05:27:35 +0200
commit82effb3fc7bcab0efcc343b3e03355f5f2f663c9 (patch)
tree995f05032a679288318f6d54911f62b5a330c406 /sapi/cli
parent2d5f277a2d7129c58dce46270768787c145e79fb (diff)
downloadphp-git-82effb3fc7bcab0efcc343b3e03355f5f2f663c9.tar.gz
implement support for workers in cli-server on platforms supporting fork
Diffstat (limited to 'sapi/cli')
-rw-r--r--sapi/cli/php_cli_server.c110
1 files changed, 104 insertions, 6 deletions
diff --git a/sapi/cli/php_cli_server.c b/sapi/cli/php_cli_server.c
index be64ff9924..bfdf27f8d6 100644
--- a/sapi/cli/php_cli_server.c
+++ b/sapi/cli/php_cli_server.c
@@ -101,6 +101,13 @@
#define OUTPUT_IS_TTY 1
#define OUTPUT_NOT_TTY 0
+#if HAVE_FORK
+# include <sys/wait.h>
+static pid_t php_cli_server_master;
+static pid_t *php_cli_server_workers;
+static zend_long php_cli_server_workers_max;
+#endif
+
typedef struct php_cli_server_poller {
fd_set rfds, wfds;
struct {
@@ -483,9 +490,57 @@ const zend_function_entry server_additional_functions[] = {
static int sapi_cli_server_startup(sapi_module_struct *sapi_module) /* {{{ */
{
+ char *workers;
+
if (php_module_startup(sapi_module, &cli_server_module_entry, 1) == FAILURE) {
return FAILURE;
}
+
+ if ((workers = getenv("PHP_CLI_SERVER_WORKERS"))) {
+#ifndef SO_REUSEPORT
+ fprintf(stderr, "platform does not support SO_REUSEPORT, cannot create workers\n");
+#elif HAVE_FORK
+ ZEND_ATOL(php_cli_server_workers_max, workers);
+
+ if (php_cli_server_workers_max > 1) {
+ zend_long php_cli_server_worker;
+
+ php_cli_server_workers = calloc(
+ php_cli_server_workers_max, sizeof(pid_t));
+ if (!php_cli_server_workers) {
+ php_cli_server_workers_max = 1;
+
+ return SUCCESS;
+ }
+
+ php_cli_server_master = getpid();
+
+ for (php_cli_server_worker = 0;
+ php_cli_server_worker < php_cli_server_workers_max;
+ php_cli_server_worker++) {
+ pid_t pid = fork();
+
+ if (pid == FAILURE) {
+ /* no more forks allowed, work with what we have ... */
+ php_cli_server_workers_max =
+ php_cli_server_worker + 1;
+ return SUCCESS;
+ } else if (pid == SUCCESS) {
+ return SUCCESS;
+ } else {
+ php_cli_server_workers[
+ php_cli_server_worker
+ ] = pid;
+ }
+ }
+ } else {
+ fprintf(stderr, "number of workers must be larger than 1\n");
+ }
+#else
+ fprintf(stderr, "forking is not supported on this platform\n");
+#endif
+ }
+
return SUCCESS;
} /* }}} */
@@ -703,7 +758,15 @@ static void sapi_cli_server_log_message(char *msg, int syslog_type_int) /* {{{ *
memmove(buf, "unknown", sizeof("unknown"));
}
}
- fprintf(stderr, "[%s] %s\n", buf, msg);
+#ifdef HAVE_FORK
+ if (php_cli_server_workers_max > 1) {
+ fprintf(stderr, "[%ld] [%s] %s\n", (long) getpid(), buf, msg);
+ } else {
+ fprintf(stderr, "[%s] %s\n", buf, msg);
+ }
+#else
+ fprintf(stderr, "[%s] %s\n", buf, msg);
+#endif
} /* }}} */
/* {{{ sapi_module_struct cli_server_sapi_module
@@ -1231,6 +1294,13 @@ static php_socket_t php_network_listen_socket(const char *host, int *port, int s
}
#endif
+#if defined(HAVE_FORK) && defined(SO_REUSEPORT)
+ if (php_cli_server_workers_max > 1) {
+ int val = 1;
+ setsockopt(retval, SOL_SOCKET, SO_REUSEPORT, (char*)&val, sizeof(val));
+ }
+#endif
+
if (bind(retval, sa, *socklen) == SOCK_CONN_ERR) {
err = php_socket_errno();
if (err == SOCK_EINVAL || err == SOCK_EADDRINUSE) {
@@ -2219,6 +2289,32 @@ static void php_cli_server_dtor(php_cli_server *server) /* {{{ */
if (server->router) {
pefree(server->router, 1);
}
+#if HAVE_FORK
+ if (php_cli_server_workers_max > 1 &&
+ php_cli_server_workers &&
+ getpid() == php_cli_server_master) {
+ zend_long php_cli_server_worker;
+
+ for (php_cli_server_worker = 0;
+ php_cli_server_worker < php_cli_server_workers_max;
+ php_cli_server_worker++) {
+ int php_cli_server_worker_status;
+
+ do {
+ if (waitpid(php_cli_server_workers[php_cli_server_worker],
+ &php_cli_server_worker_status,
+ 0) == FAILURE) {
+ /* an extremely bad thing happened */
+ break;
+ }
+
+ } while (!WIFEXITED(php_cli_server_worker_status) &&
+ !WIFSIGNALED(php_cli_server_worker_status));
+ }
+
+ free(php_cli_server_workers);
+ }
+#endif
} /* }}} */
static void php_cli_server_client_dtor_wrapper(zval *zv) /* {{{ */
@@ -2593,11 +2689,13 @@ int do_cli_server(int argc, char **argv) /* {{{ */
memmove(buf, "unknown time, can't be fetched", sizeof("unknown time, can't be fetched"));
}
- printf("PHP %s Development Server started at %s"
- "Listening on http://%s\n"
- "Document root is %s\n"
- "Press Ctrl-C to quit.\n",
- PHP_VERSION, buf, server_bind_address, document_root);
+#if HAVE_FORK
+ printf("[%ld] PHP %s Development Server (http://%s) started at %s",
+ (long) getpid(), PHP_VERSION, server_bind_address, buf);
+#else
+ printf("PHP %s Development Server (http://%s) started at %s",
+ PHP_VERSION, server_bind_address, buf);
+#endif
}
#if defined(SIGINT)