1
0
mirror of https://github.com/php/php-src.git synced 2026-03-24 00:02:20 +01:00

Fixed fpm-side (tests passes)

This commit is contained in:
Xinchen Hui
2015-05-23 10:31:50 +08:00
parent fef18f4bea
commit 18cf4e0a8a
9 changed files with 437 additions and 1755 deletions

View File

@@ -20,7 +20,6 @@
#include "php.h"
#include "php_network.h"
#include "fastcgi.h"
#include <string.h>
#include <stdlib.h>
@@ -32,8 +31,6 @@
#define MAXFQDNLEN 255
#endif
static fcgi_logger flog;
#ifdef _WIN32
#include <windows.h>
@@ -133,10 +130,16 @@ static int is_impersonate = 0;
#endif
#include "fastcgi.h"
/* maybe it's better to use weak name instead */
static fcgi_logger logger;
typedef union _sa_t {
struct sockaddr sa;
struct sockaddr_un sa_unix;
struct sockaddr_in sa_inet;
struct sockaddr_in6 sa_inet6;
} sa_t;
static HashTable fcgi_mgmt_vars;
@@ -144,44 +147,10 @@ static HashTable fcgi_mgmt_vars;
static int is_initialized = 0;
static int is_fastcgi = 0;
static int in_shutdown = 0;
static in_addr_t *allowed_clients = NULL;
static sa_t *allowed_clients = NULL;
static sa_t client_sa;
/* hash table */
#define FCGI_HASH_TABLE_SIZE 128
#define FCGI_HASH_TABLE_MASK (FCGI_HASH_TABLE_SIZE - 1)
#define FCGI_HASH_SEG_SIZE 4096
typedef struct _fcgi_hash_bucket {
unsigned int hash_value;
unsigned int var_len;
char *var;
unsigned int val_len;
char *val;
struct _fcgi_hash_bucket *next;
struct _fcgi_hash_bucket *list_next;
} fcgi_hash_bucket;
typedef struct _fcgi_hash_buckets {
unsigned int idx;
struct _fcgi_hash_buckets *next;
struct _fcgi_hash_bucket data[FCGI_HASH_TABLE_SIZE];
} fcgi_hash_buckets;
typedef struct _fcgi_data_seg {
char *pos;
char *end;
struct _fcgi_data_seg *next;
char data[1];
} fcgi_data_seg;
typedef struct _fcgi_hash {
fcgi_hash_bucket *hash_table[FCGI_HASH_TABLE_SIZE];
fcgi_hash_bucket *list;
fcgi_hash_buckets *buckets;
fcgi_data_seg *data;
} fcgi_hash;
static void fcgi_hash_init(fcgi_hash *h)
{
memset(h->hash_table, 0, sizeof(h->hash_table));
@@ -341,29 +310,6 @@ static void fcgi_hash_apply(fcgi_hash *h, fcgi_apply_func func, void *arg)
}
}
struct _fcgi_request {
int listen_socket;
int tcp;
int fd;
int id;
int keep;
#ifdef TCP_NODELAY
int nodelay;
#endif
int closed;
int in_len;
int in_pad;
fcgi_header *out_hdr;
unsigned char *out_pos;
unsigned char out_buf[1024*8];
unsigned char reserved[sizeof(fcgi_end_request_rec)];
int has_env;
fcgi_hash env;
};
#ifdef _WIN32
static DWORD WINAPI fcgi_shutdown_thread(LPVOID arg)
@@ -399,6 +345,11 @@ static void fcgi_setup_signals(void)
}
#endif
void fcgi_set_in_shutdown(int new_value)
{
in_shutdown = new_value;
}
int fcgi_in_shutdown(void)
{
return in_shutdown;
@@ -409,8 +360,8 @@ void fcgi_terminate(void)
in_shutdown = 1;
}
void fcgi_set_logger(fcgi_logger logger) {
flog = logger;
void fcgi_set_logger(fcgi_logger lg) {
logger = lg;
}
int fcgi_init(void)
@@ -632,10 +583,10 @@ int fcgi_listen(const char *path, int backlog)
hep = gethostbyname(host);
}
if (!hep || hep->h_addrtype != AF_INET || !hep->h_addr_list[0]) {
flog(FCGI_ERROR, "Cannot resolve host name '%s'!\n", host);
logger(FCGI_ERROR, "Cannot resolve host name '%s'!\n", host);
return -1;
} else if (hep->h_addr_list[1]) {
flog(FCGI_ERROR, "Host '%s' has multiple addresses. You must choose one explicitly!\n", host);
logger(FCGI_ERROR, "Host '%s' has multiple addresses. You must choose one explicitly!\n", host);
return -1;
}
sa.sa_inet.sin_addr.s_addr = ((struct in_addr*)hep->h_addr_list[0])->s_addr;
@@ -672,7 +623,7 @@ int fcgi_listen(const char *path, int backlog)
int path_len = strlen(path);
if (path_len >= sizeof(sa.sa_unix.sun_path)) {
flog(FCGI_ERROR, "Listening socket's path name is too long.\n");
logger(FCGI_ERROR, "Listening socket's path name is too long.\n");
return -1;
}
@@ -695,7 +646,7 @@ int fcgi_listen(const char *path, int backlog)
bind(listen_socket, (struct sockaddr *) &sa, sock_len) < 0 ||
listen(listen_socket, backlog) < 0) {
flog(FCGI_ERROR, "Cannot bind/listen socket - [%d] %s.\n",errno, strerror(errno));
logger(FCGI_ERROR, "Cannot bind/listen socket - [%d] %s.\n",errno, strerror(errno));
return -1;
}
@@ -714,7 +665,7 @@ int fcgi_listen(const char *path, int backlog)
if (*cur == ',') n++;
cur++;
}
allowed_clients = malloc(sizeof(in_addr_t) * (n+2));
allowed_clients = malloc(sizeof(sa_t) * (n+2));
n = 0;
cur = ip;
while (cur) {
@@ -723,15 +674,25 @@ int fcgi_listen(const char *path, int backlog)
*end = 0;
end++;
}
allowed_clients[n] = inet_addr(cur);
if (allowed_clients[n] == INADDR_NONE) {
flog(FCGI_ERROR, "Wrong IP address '%s' in FCGI_WEB_SERVER_ADDRS\n", cur);
if (inet_pton(AF_INET, cur, &allowed_clients[n].sa_inet.sin_addr)>0) {
allowed_clients[n].sa.sa_family = AF_INET;
n++;
#ifdef HAVE_IPV6
} else if (inet_pton(AF_INET6, cur, &allowed_clients[n].sa_inet6.sin6_addr)>0) {
allowed_clients[n].sa.sa_family = AF_INET6;
n++;
#endif
} else {
logger(FCGI_ERROR, "Wrong IP address '%s' in listen.allowed_clients", cur);
}
n++;
cur = end;
}
allowed_clients[n] = INADDR_NONE;
allowed_clients[n].sa.sa_family = 0;
free(ip);
if (!n) {
logger(FCGI_ERROR, "There are no allowed addresses");
/* don't clear allowed_clients as it will create an "open for all" security issue */
}
}
}
@@ -750,38 +711,81 @@ int fcgi_listen(const char *path, int backlog)
return listen_socket;
}
fcgi_request *fcgi_init_request(int listen_socket)
void fcgi_set_allowed_clients(char *ip)
{
fcgi_request *req = (fcgi_request*)calloc(1, sizeof(fcgi_request));
char *cur, *end;
int n;
if (ip) {
ip = strdup(ip);
cur = ip;
n = 0;
while (*cur) {
if (*cur == ',') n++;
cur++;
}
if (allowed_clients) free(allowed_clients);
allowed_clients = malloc(sizeof(sa_t) * (n+2));
n = 0;
cur = ip;
while (cur) {
end = strchr(cur, ',');
if (end) {
*end = 0;
end++;
}
if (inet_pton(AF_INET, cur, &allowed_clients[n].sa_inet.sin_addr)>0) {
allowed_clients[n].sa.sa_family = AF_INET;
n++;
#ifdef HAVE_IPV6
} else if (inet_pton(AF_INET6, cur, &allowed_clients[n].sa_inet6.sin6_addr)>0) {
allowed_clients[n].sa.sa_family = AF_INET6;
n++;
#endif
} else {
logger(FCGI_ERROR, "Wrong IP address '%s' in listen.allowed_clients", cur);
}
cur = end;
}
allowed_clients[n].sa.sa_family = 0;
free(ip);
if (!n) {
logger(FCGI_ERROR, "There are no allowed addresses");
/* don't clear allowed_clients as it will create an "open for all" security issue */
}
}
}
fcgi_request *fcgi_init_request(fcgi_request *req, int listen_socket)
{
memset(req, 0, sizeof(fcgi_request));
req->listen_socket = listen_socket;
req->fd = -1;
req->id = -1;
/*
req->in_len = 0;
req->in_pad = 0;
req->out_hdr = NULL;
#ifdef TCP_NODELAY
req->nodelay = 0;
#endif
req->env = NULL;
req->has_env = 0;
*/
req->out_pos = req->out_buf;
#ifdef _WIN32
req->tcp = !GetNamedPipeInfo((HANDLE)_get_osfhandle(req->listen_socket), NULL, NULL, NULL, NULL);
#endif
#ifdef TCP_NODELAY
req->nodelay = 0;
#endif
fcgi_hash_init(&req->env);
return req;
}
void fcgi_destroy_request(fcgi_request *req)
{
fcgi_hash_destroy(&req->env);
free(req);
}
static inline ssize_t safe_write(fcgi_request *req, const void *buf, size_t count)
{
int ret;
@@ -919,6 +923,7 @@ static int fcgi_read_request(fcgi_request *req)
req->in_len = 0;
req->out_hdr = NULL;
req->out_pos = req->out_buf;
fcgi_hash_init(&req->env);
req->has_env = 1;
if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) ||
@@ -1058,7 +1063,7 @@ static int fcgi_read_request(fcgi_request *req)
}
len = (int)(p - buf - sizeof(fcgi_header));
len += fcgi_make_header((fcgi_header*)buf, FCGI_GET_VALUES_RESULT, 0, len);
if (safe_write(req, buf, sizeof(fcgi_header)+len) != (int)sizeof(fcgi_header)+len) {
if (safe_write(req, buf, sizeof(fcgi_header) + len) != (ssize_t)sizeof(fcgi_header)+len) {
req->keep = 0;
return 0;
}
@@ -1123,10 +1128,11 @@ int fcgi_read(fcgi_request *req, char *str, int len)
return n;
}
static inline void fcgi_close(fcgi_request *req, int force, int destroy)
void fcgi_close(fcgi_request *req, int force, int destroy)
{
if (destroy && req->has_env) {
fcgi_hash_clean(&req->env);
fcgi_hash_destroy(&req->env);
req->has_env = 0;
}
@@ -1169,9 +1175,57 @@ static inline void fcgi_close(fcgi_request *req, int force, int destroy)
req->nodelay = 0;
#endif
req->fd = -1;
if (req->hook.on_close) {
req->hook.on_close();
}
}
}
int fcgi_is_closed(fcgi_request *req)
{
return (req->fd < 0);
}
static int fcgi_is_allowed() {
int i;
if (client_sa.sa.sa_family == AF_UNIX) {
return 1;
}
if (!allowed_clients) {
return 1;
}
if (client_sa.sa.sa_family == AF_INET) {
for (i = 0; allowed_clients[i].sa.sa_family ; i++) {
if (allowed_clients[i].sa.sa_family == AF_INET
&& !memcmp(&client_sa.sa_inet.sin_addr, &allowed_clients[i].sa_inet.sin_addr, 4)) {
return 1;
}
}
}
#ifdef HAVE_IPV6
if (client_sa.sa.sa_family == AF_INET6) {
for (i = 0; allowed_clients[i].sa.sa_family ; i++) {
if (allowed_clients[i].sa.sa_family == AF_INET6
&& !memcmp(&client_sa.sa_inet6.sin6_addr, &allowed_clients[i].sa_inet6.sin6_addr, 12)) {
return 1;
}
#ifdef IN6_IS_ADDR_V4MAPPED
if (allowed_clients[i].sa.sa_family == AF_INET
&& IN6_IS_ADDR_V4MAPPED(&client_sa.sa_inet6.sin6_addr)
&& !memcmp(((char *)&client_sa.sa_inet6.sin6_addr)+12, &allowed_clients[i].sa_inet.sin_addr, 4)) {
return 1;
}
#endif
}
}
#endif
logger(FCGI_ERROR, "Connection disallowed: IP address '%s' has been dropped.", fcgi_get_last_client_ip());
return 0;
}
int fcgi_accept_request(fcgi_request *req)
{
#ifdef _WIN32
@@ -1215,37 +1269,19 @@ int fcgi_accept_request(fcgi_request *req)
sa_t sa;
socklen_t len = sizeof(sa);
if (req->hook.on_accept) {
req->hook.on_accept();
}
FCGI_LOCK(req->listen_socket);
req->fd = accept(listen_socket, (struct sockaddr *)&sa, &len);
FCGI_UNLOCK(req->listen_socket);
if (req->fd >= 0) {
if (((struct sockaddr *)&sa)->sa_family == AF_INET) {
#ifndef _WIN32
req->tcp = 1;
#endif
if (allowed_clients) {
int n = 0;
int allowed = 0;
while (allowed_clients[n] != INADDR_NONE) {
if (allowed_clients[n] == sa.sa_inet.sin_addr.s_addr) {
allowed = 1;
break;
}
n++;
}
if (!allowed) {
flog(FCGI_ERROR, "Connection from disallowed IP address '%s' is dropped.\n", inet_ntoa(sa.sa_inet.sin_addr));
closesocket(req->fd);
req->fd = -1;
continue;
}
}
#ifndef _WIN32
} else {
req->tcp = 0;
#endif
}
client_sa = sa;
if (req->fd >= 0 && !fcgi_is_allowed()) {
closesocket(req->fd);
req->fd = -1;
continue;
}
}
@@ -1265,6 +1301,10 @@ int fcgi_accept_request(fcgi_request *req)
struct pollfd fds;
int ret;
if (req->hook.on_read) {
req->hook.on_read();
}
fds.fd = req->fd;
fds.events = POLLIN;
fds.revents = 0;
@@ -1277,6 +1317,10 @@ int fcgi_accept_request(fcgi_request *req)
}
fcgi_close(req, 1, 0);
#else
if (req->hook.on_read) {
req->hook.on_read();
}
if (req->fd < FD_SETSIZE) {
struct timeval tv = {5,0};
fd_set set;
@@ -1293,7 +1337,7 @@ int fcgi_accept_request(fcgi_request *req)
}
fcgi_close(req, 1, 0);
} else {
flog(FCGI_ERROR, "Too many open file descriptors. FD_SETSIZE limit exceeded.");
logger(FCGI_ERROR, "Too many open file descriptors. FD_SETSIZE limit exceeded.");
fcgi_close(req, 1, 0);
}
#endif
@@ -1560,6 +1604,31 @@ void fcgi_free_mgmt_var_cb(zval *zv)
pefree(Z_STR_P(zv), 1);
}
const char *fcgi_get_last_client_ip()
{
static char str[INET6_ADDRSTRLEN];
/* Ipv4 */
if (client_sa.sa.sa_family == AF_INET) {
return inet_ntop(client_sa.sa.sa_family, &client_sa.sa_inet.sin_addr, str, INET6_ADDRSTRLEN);
}
#ifdef HAVE_IPV6
#ifdef IN6_IS_ADDR_V4MAPPED
/* Ipv4-Mapped-Ipv6 */
if (client_sa.sa.sa_family == AF_INET6
&& IN6_IS_ADDR_V4MAPPED(&client_sa.sa_inet6.sin6_addr)) {
return inet_ntop(AF_INET, ((char *)&client_sa.sa_inet6.sin6_addr)+12, str, INET6_ADDRSTRLEN);
}
#endif
/* Ipv6 */
if (client_sa.sa.sa_family == AF_INET6) {
return inet_ntop(client_sa.sa.sa_family, &client_sa.sa_inet6.sin6_addr, str, INET6_ADDRSTRLEN);
}
#endif
/* Unix socket */
return NULL;
}
/*
* Local variables:
* tab-width: 4

View File

@@ -49,11 +49,13 @@ typedef enum _fcgi_role {
FCGI_FILTER = 3
} fcgi_role;
typedef enum _fcgi_code {
FCGI_NOTICE,
FCGI_WARNING,
FCGI_ERROR,
} fcgi_code;
enum {
FCGI_DEBUG = 1,
FCGI_NOTICE = 2,
FCGI_WARNING = 3,
FCGI_ERROR = 4,
FCGI_ALERT = 5,
};
typedef enum _fcgi_request_type {
FCGI_BEGIN_REQUEST = 1, /* [in] */
@@ -116,21 +118,91 @@ typedef struct _fcgi_end_request_rec {
typedef void (*fcgi_apply_func)(char *var, unsigned int var_len, char *val, unsigned int val_len, void *arg);
typedef void (*fcgi_logger)(int type, const char *format, ...);
typedef void (*fcgi_logger)(int type, const char *fmt, ...);
typedef struct _fcgi_request fcgi_request;
#define FCGI_HASH_TABLE_SIZE 128
#define FCGI_HASH_TABLE_MASK (FCGI_HASH_TABLE_SIZE - 1)
#define FCGI_HASH_SEG_SIZE 4096
typedef struct _fcgi_hash_bucket {
unsigned int hash_value;
unsigned int var_len;
char *var;
unsigned int val_len;
char *val;
struct _fcgi_hash_bucket *next;
struct _fcgi_hash_bucket *list_next;
} fcgi_hash_bucket;
typedef struct _fcgi_hash_buckets {
unsigned int idx;
struct _fcgi_hash_buckets *next;
struct _fcgi_hash_bucket data[FCGI_HASH_TABLE_SIZE];
} fcgi_hash_buckets;
typedef struct _fcgi_data_seg {
char *pos;
char *end;
struct _fcgi_data_seg *next;
char data[1];
} fcgi_data_seg;
typedef struct _fcgi_hash {
fcgi_hash_bucket *hash_table[FCGI_HASH_TABLE_SIZE];
fcgi_hash_bucket *list;
fcgi_hash_buckets *buckets;
fcgi_data_seg *data;
} fcgi_hash;
typedef struct _fcgi_request fcgi_request;
typedef struct _fcgi_req_hook fcgi_req_hook;
struct _fcgi_req_hook {
void(*on_accept)();
void(*on_read)();
void(*on_close)();
};
struct _fcgi_request {
int listen_socket;
int tcp;
int fd;
int id;
int keep;
#ifdef TCP_NODELAY
int nodelay;
#endif
int closed;
fcgi_req_hook hook;
int in_len;
int in_pad;
fcgi_header *out_hdr;
unsigned char *out_pos;
unsigned char out_buf[1024*8];
unsigned char reserved[sizeof(fcgi_end_request_rec)];
int has_env;
fcgi_hash env;
};
int fcgi_init(void);
void fcgi_shutdown(void);
int fcgi_is_fastcgi(void);
int fcgi_is_closed(fcgi_request *req);
void fcgi_close(fcgi_request *req, int force, int destroy);
int fcgi_in_shutdown(void);
void fcgi_terminate(void);
int fcgi_listen(const char *path, int backlog);
fcgi_request* fcgi_init_request(int listen_socket);
void fcgi_destroy_request(fcgi_request *req);
fcgi_request* fcgi_init_request(fcgi_request *request, int listen_socket);
void fcgi_set_allowed_clients(char *ip);
int fcgi_accept_request(fcgi_request *req);
int fcgi_finish_request(fcgi_request *req, int force_close);
void fcgi_set_logger(fcgi_logger logger);
void fcgi_set_logger(fcgi_logger lg);
const char *fcgi_get_last_client_ip();
void fcgi_set_in_shutdown(int new_value);
char* fcgi_getenv(fcgi_request *req, const char* var, int var_len);
char* fcgi_putenv(fcgi_request *req, char* var, int var_len, char* val);

View File

@@ -1034,12 +1034,12 @@ static int is_valid_path(const char *path)
/* }}} */
#define CGI_GETENV(name) \
((request) ? \
((request->has_env) ? \
FCGI_GETENV(request, name) : \
getenv(name))
#define CGI_PUTENV(name, value) \
((request) ? \
((request->has_env) ? \
FCGI_PUTENV(request, name, value) : \
_sapi_cgi_putenv(name, sizeof(name)-1, value))
@@ -1732,7 +1732,7 @@ int main(int argc, char *argv[])
int fastcgi;
char *bindpath = NULL;
int fcgi_fd = 0;
fcgi_request *request = NULL;
fcgi_request request = {0};
int warmup_repeats = 0;
int repeats = 1;
int benchmark = 0;
@@ -1967,109 +1967,109 @@ consult the installation file that came with this distribution, or visit \n\
php_import_environment_variables = cgi_php_import_environment_variables;
/* library is already initialized, now init our request */
request = fcgi_init_request(fcgi_fd);
fcgi_init_request(&request, fcgi_fd);
#ifndef PHP_WIN32
/* Pre-fork, if required */
if (getenv("PHP_FCGI_CHILDREN")) {
char * children_str = getenv("PHP_FCGI_CHILDREN");
children = atoi(children_str);
if (children < 0) {
fprintf(stderr, "PHP_FCGI_CHILDREN is not valid\n");
return FAILURE;
}
fcgi_set_mgmt_var("FCGI_MAX_CONNS", sizeof("FCGI_MAX_CONNS")-1, children_str, strlen(children_str));
/* This is the number of concurrent requests, equals FCGI_MAX_CONNS */
fcgi_set_mgmt_var("FCGI_MAX_REQS", sizeof("FCGI_MAX_REQS")-1, children_str, strlen(children_str));
} else {
fcgi_set_mgmt_var("FCGI_MAX_CONNS", sizeof("FCGI_MAX_CONNS")-1, "1", sizeof("1")-1);
fcgi_set_mgmt_var("FCGI_MAX_REQS", sizeof("FCGI_MAX_REQS")-1, "1", sizeof("1")-1);
}
if (children) {
int running = 0;
pid_t pid;
/* Create a process group for ourself & children */
setsid();
pgroup = getpgrp();
#ifdef DEBUG_FASTCGI
fprintf(stderr, "Process group %d\n", pgroup);
#endif
/* Set up handler to kill children upon exit */
act.sa_flags = 0;
act.sa_handler = fastcgi_cleanup;
if (sigaction(SIGTERM, &act, &old_term) ||
sigaction(SIGINT, &act, &old_int) ||
sigaction(SIGQUIT, &act, &old_quit)
) {
perror("Can't set signals");
exit(1);
/* Pre-fork, if required */
if (getenv("PHP_FCGI_CHILDREN")) {
char * children_str = getenv("PHP_FCGI_CHILDREN");
children = atoi(children_str);
if (children < 0) {
fprintf(stderr, "PHP_FCGI_CHILDREN is not valid\n");
return FAILURE;
}
fcgi_set_mgmt_var("FCGI_MAX_CONNS", sizeof("FCGI_MAX_CONNS")-1, children_str, strlen(children_str));
/* This is the number of concurrent requests, equals FCGI_MAX_CONNS */
fcgi_set_mgmt_var("FCGI_MAX_REQS", sizeof("FCGI_MAX_REQS")-1, children_str, strlen(children_str));
} else {
fcgi_set_mgmt_var("FCGI_MAX_CONNS", sizeof("FCGI_MAX_CONNS")-1, "1", sizeof("1")-1);
fcgi_set_mgmt_var("FCGI_MAX_REQS", sizeof("FCGI_MAX_REQS")-1, "1", sizeof("1")-1);
}
if (fcgi_in_shutdown()) {
goto parent_out;
}
if (children) {
int running = 0;
pid_t pid;
while (parent) {
do {
/* Create a process group for ourself & children */
setsid();
pgroup = getpgrp();
#ifdef DEBUG_FASTCGI
fprintf(stderr, "Forking, %d running\n", running);
fprintf(stderr, "Process group %d\n", pgroup);
#endif
pid = fork();
switch (pid) {
case 0:
/* One of the children.
* Make sure we don't go round the
* fork loop any more
*/
parent = 0;
/* don't catch our signals */
sigaction(SIGTERM, &old_term, 0);
sigaction(SIGQUIT, &old_quit, 0);
sigaction(SIGINT, &old_int, 0);
break;
case -1:
perror("php (pre-forking)");
exit(1);
break;
default:
/* Fine */
running++;
break;
}
} while (parent && (running < children));
/* Set up handler to kill children upon exit */
act.sa_flags = 0;
act.sa_handler = fastcgi_cleanup;
if (sigaction(SIGTERM, &act, &old_term) ||
sigaction(SIGINT, &act, &old_int) ||
sigaction(SIGQUIT, &act, &old_quit)
) {
perror("Can't set signals");
exit(1);
}
if (parent) {
if (fcgi_in_shutdown()) {
goto parent_out;
}
while (parent) {
do {
#ifdef DEBUG_FASTCGI
fprintf(stderr, "Wait for kids, pid %d\n", getpid());
fprintf(stderr, "Forking, %d running\n", running);
#endif
parent_waiting = 1;
while (1) {
if (wait(&status) >= 0) {
running--;
pid = fork();
switch (pid) {
case 0:
/* One of the children.
* Make sure we don't go round the
* fork loop any more
*/
parent = 0;
/* don't catch our signals */
sigaction(SIGTERM, &old_term, 0);
sigaction(SIGQUIT, &old_quit, 0);
sigaction(SIGINT, &old_int, 0);
break;
} else if (exit_signal) {
case -1:
perror("php (pre-forking)");
exit(1);
break;
default:
/* Fine */
running++;
break;
}
}
if (exit_signal) {
#if 0
while (running > 0) {
while (wait(&status) < 0) {
} while (parent && (running < children));
if (parent) {
#ifdef DEBUG_FASTCGI
fprintf(stderr, "Wait for kids, pid %d\n", getpid());
#endif
parent_waiting = 1;
while (1) {
if (wait(&status) >= 0) {
running--;
break;
} else if (exit_signal) {
break;
}
running--;
}
if (exit_signal) {
#if 0
while (running > 0) {
while (wait(&status) < 0) {
}
running--;
}
#endif
goto parent_out;
goto parent_out;
}
}
}
} else {
parent = 0;
}
} else {
parent = 0;
}
#endif /* WIN32 */
}
@@ -2096,9 +2096,6 @@ consult the installation file that came with this distribution, or visit \n\
break;
case 'h':
case '?':
if (request) {
fcgi_destroy_request(request);
}
fcgi_shutdown();
no_headers = 1;
SG(headers_sent) = 1;
@@ -2120,9 +2117,9 @@ consult the installation file that came with this distribution, or visit \n\
fcgi_impersonate();
}
#endif
while (!fastcgi || fcgi_accept_request(request) >= 0) {
SG(server_context) = fastcgi ? (void *) request : (void *) 1;
init_request_info(request);
while (!fastcgi || fcgi_accept_request(&request) >= 0) {
SG(server_context) = fastcgi ? (void *)&request : (void *) 1;
init_request_info(&request);
if (!cgi && !fastcgi) {
while ((c = php_getopt(argc, argv, OPTIONS, &php_optarg, &php_optind, 0, 2)) != -1) {
@@ -2307,7 +2304,7 @@ consult the installation file that came with this distribution, or visit \n\
* get path_translated */
if (php_request_startup() == FAILURE) {
if (fastcgi) {
fcgi_finish_request(request, 1);
fcgi_finish_request(&request, 1);
}
SG(server_context) = NULL;
php_module_shutdown();
@@ -2518,7 +2515,7 @@ fastcgi_request_done:
/* only fastcgi will get here */
requests++;
if (max_requests && (requests == max_requests)) {
fcgi_finish_request(request, 1);
fcgi_finish_request(&request, 1);
if (bindpath) {
free(bindpath);
}
@@ -2530,9 +2527,6 @@ fastcgi_request_done:
}
/* end of fastcgi loop */
}
if (request) {
fcgi_destroy_request(request);
}
fcgi_shutdown();
if (cgi_sapi_module.php_ini_path_override) {

View File

@@ -678,8 +678,7 @@ if test "$PHP_FPM" != "no"; then
PHP_FPM_CFLAGS="-I$abs_srcdir/sapi/fpm"
PHP_FPM_FILES="fpm/fastcgi.c \
fpm/fpm.c \
PHP_FPM_FILES="fpm/fpm.c \
fpm/fpm_children.c \
fpm/fpm_cleanup.c \
fpm/fpm_clock.c \

File diff suppressed because it is too large Load Diff

View File

@@ -1,151 +0,0 @@
/*
+----------------------------------------------------------------------+
| PHP Version 7 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2015 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Authors: Dmitry Stogov <dmitry@zend.com> |
+----------------------------------------------------------------------+
*/
/* $Id: fastcgi.h 272370 2008-12-31 11:15:49Z sebastian $ */
/* FastCGI protocol */
#define FCGI_VERSION_1 1
#define FCGI_MAX_LENGTH 0xffff
#define FCGI_KEEP_CONN 1
/* this is near the perfect hash function for most useful FastCGI variables
* which combines efficiency and minimal hash collisions
*/
#define FCGI_HASH_FUNC(var, var_len) \
(UNEXPECTED(var_len < 3) ? var_len : \
(((unsigned int)var[3]) << 2) + \
(((unsigned int)var[var_len-2]) << 4) + \
(((unsigned int)var[var_len-1]) << 2) + \
var_len)
#define FCGI_GETENV(request, name) \
fcgi_quick_getenv(request, name, sizeof(name)-1, FCGI_HASH_FUNC(name, sizeof(name)-1))
#define FCGI_PUTENV(request, name, value) \
fcgi_quick_putenv(request, name, sizeof(name)-1, FCGI_HASH_FUNC(name, sizeof(name)-1), value)
typedef enum _fcgi_role {
FCGI_RESPONDER = 1,
FCGI_AUTHORIZER = 2,
FCGI_FILTER = 3
} fcgi_role;
typedef enum _fcgi_request_type {
FCGI_BEGIN_REQUEST = 1, /* [in] */
FCGI_ABORT_REQUEST = 2, /* [in] (not supported) */
FCGI_END_REQUEST = 3, /* [out] */
FCGI_PARAMS = 4, /* [in] environment variables */
FCGI_STDIN = 5, /* [in] post data */
FCGI_STDOUT = 6, /* [out] response */
FCGI_STDERR = 7, /* [out] errors */
FCGI_DATA = 8, /* [in] filter data (not supported) */
FCGI_GET_VALUES = 9, /* [in] */
FCGI_GET_VALUES_RESULT = 10 /* [out] */
} fcgi_request_type;
typedef enum _fcgi_protocol_status {
FCGI_REQUEST_COMPLETE = 0,
FCGI_CANT_MPX_CONN = 1,
FCGI_OVERLOADED = 2,
FCGI_UNKNOWN_ROLE = 3
} dcgi_protocol_status;
typedef struct _fcgi_header {
unsigned char version;
unsigned char type;
unsigned char requestIdB1;
unsigned char requestIdB0;
unsigned char contentLengthB1;
unsigned char contentLengthB0;
unsigned char paddingLength;
unsigned char reserved;
} fcgi_header;
typedef struct _fcgi_begin_request {
unsigned char roleB1;
unsigned char roleB0;
unsigned char flags;
unsigned char reserved[5];
} fcgi_begin_request;
typedef struct _fcgi_begin_request_rec {
fcgi_header hdr;
fcgi_begin_request body;
} fcgi_begin_request_rec;
typedef struct _fcgi_end_request {
unsigned char appStatusB3;
unsigned char appStatusB2;
unsigned char appStatusB1;
unsigned char appStatusB0;
unsigned char protocolStatus;
unsigned char reserved[3];
} fcgi_end_request;
typedef struct _fcgi_end_request_rec {
fcgi_header hdr;
fcgi_end_request body;
} fcgi_end_request_rec;
/* FastCGI client API */
typedef void (*fcgi_apply_func)(char *var, unsigned int var_len, char *val, unsigned int val_len, void *arg);
typedef struct _fcgi_request fcgi_request;
int fcgi_init(void);
void fcgi_shutdown(void);
int fcgi_in_shutdown(void);
void fcgi_terminate(void);
fcgi_request* fcgi_init_request(int listen_socket);
void fcgi_destroy_request(fcgi_request *req);
int fcgi_accept_request(fcgi_request *req);
int fcgi_finish_request(fcgi_request *req, int force_close);
void fcgi_set_allowed_clients(char *);
void fcgi_close(fcgi_request *req, int force, int destroy);
int fcgi_is_closed(fcgi_request *req);
char* fcgi_getenv(fcgi_request *req, const char* var, int var_len);
char* fcgi_putenv(fcgi_request *req, char* var, int var_len, char* val);
char* fcgi_quick_getenv(fcgi_request *req, const char* var, int var_len, unsigned int hash_value);
char* fcgi_quick_putenv(fcgi_request *req, char* var, int var_len, unsigned int hash_value, char* val);
void fcgi_loadenv(fcgi_request *req, fcgi_apply_func load_func, zval *array);
int fcgi_read(fcgi_request *req, char *str, int len);
ssize_t fcgi_write(fcgi_request *req, fcgi_request_type type, const char *str, int len);
int fcgi_flush(fcgi_request *req, int close);
void fcgi_set_mgmt_var(const char * name, size_t name_len, const char * value, size_t value_len);
void fcgi_free_mgmt_var_cb(zval *ptr);
const char *fcgi_get_last_client_ip();
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
* vim600: sw=4 ts=4 fdm=marker
* vim<600: sw=4 ts=4
*/

View File

@@ -219,14 +219,15 @@ static php_cgi_globals_struct php_cgi_globals;
#define TRANSLATE_SLASHES(path)
#endif
static int print_module_info(zval *zv)
static int print_module_info(zval *zv) /* {{{ */
{
zend_module_entry *module = Z_PTR_P(zv);
php_printf("%s\n", module->name);
return 0;
}
/* }}} */
static int module_name_cmp(const void *a, const void *b)
static int module_name_cmp(const void *a, const void *b) /* {{{ */
{
Bucket *f = (Bucket *) a;
Bucket *s = (Bucket *) b;
@@ -234,8 +235,9 @@ static int module_name_cmp(const void *a, const void *b)
return strcasecmp( ((zend_module_entry *) Z_PTR(f->val))->name,
((zend_module_entry *) Z_PTR(s->val))->name);
}
/* }}} */
static void print_modules(void)
static void print_modules(void) /* {{{ */
{
HashTable sorted_registry;
@@ -245,20 +247,23 @@ static void print_modules(void)
zend_hash_apply(&sorted_registry, print_module_info);
zend_hash_destroy(&sorted_registry);
}
/* }}} */
static int print_extension_info(zend_extension *ext, void *arg)
static int print_extension_info(zend_extension *ext, void *arg) /* {{{ */
{
php_printf("%s\n", ext->name);
return 0;
}
/* }}} */
static int extension_name_cmp(const zend_llist_element **f, const zend_llist_element **s)
static int extension_name_cmp(const zend_llist_element **f, const zend_llist_element **s) /* {{{ */
{
return strcmp( ((zend_extension *)(*f)->data)->name,
((zend_extension *)(*s)->data)->name);
}
/* }}} */
static void print_extensions(void)
static void print_extensions(void) /* {{{ */
{
zend_llist sorted_exts;
@@ -268,12 +273,13 @@ static void print_extensions(void)
zend_llist_apply_with_argument(&sorted_exts, (llist_apply_with_arg_func_t) print_extension_info, NULL);
zend_llist_destroy(&sorted_exts);
}
/* }}} */
#ifndef STDOUT_FILENO
#define STDOUT_FILENO 1
#endif
static inline size_t sapi_cgibin_single_write(const char *str, uint str_length)
static inline size_t sapi_cgibin_single_write(const char *str, uint str_length) /* {{{ */
{
ssize_t ret;
@@ -298,8 +304,9 @@ static inline size_t sapi_cgibin_single_write(const char *str, uint str_length)
return fwrite(str, 1, MIN(str_length, 16384), stdout);
#endif
}
/* }}} */
static size_t sapi_cgibin_ub_write(const char *str, size_t str_length)
static size_t sapi_cgibin_ub_write(const char *str, size_t str_length) /* {{{ */
{
const char *ptr = str;
uint remaining = str_length;
@@ -317,9 +324,9 @@ static size_t sapi_cgibin_ub_write(const char *str, size_t str_length)
return str_length;
}
/* }}} */
static void sapi_cgibin_flush(void *server_context)
static void sapi_cgibin_flush(void *server_context) /* {{{ */
{
/* fpm has started, let use fcgi instead of stdout */
if (fpm_is_running) {
@@ -339,10 +346,11 @@ static void sapi_cgibin_flush(void *server_context)
php_handle_aborted_connection();
}
}
/* }}} */
#define SAPI_CGI_MAX_HEADER_LENGTH 1024
static int sapi_cgi_send_headers(sapi_headers_struct *sapi_headers)
static int sapi_cgi_send_headers(sapi_headers_struct *sapi_headers) /* {{{ */
{
char buf[SAPI_CGI_MAX_HEADER_LENGTH];
sapi_header_struct *h;
@@ -443,12 +451,22 @@ static int sapi_cgi_send_headers(sapi_headers_struct *sapi_headers)
return SAPI_HEADER_SENT_SUCCESSFULLY;
}
/* }}} */
#ifndef STDIN_FILENO
# define STDIN_FILENO 0
#endif
static size_t sapi_cgi_read_post(char *buffer, size_t count_bytes)
static void fpm_fcgi_log(int type, const char *fmt, ...) /* {{{ */
{
va_list args;
va_start(args, fmt);
vzlog("", 0, type, fmt, args);
va_end(args);
}
/* }}} */
static size_t sapi_cgi_read_post(char *buffer, size_t count_bytes) /* {{{ */
{
uint read_bytes = 0;
int tmp_read_bytes;
@@ -486,8 +504,9 @@ static size_t sapi_cgi_read_post(char *buffer, size_t count_bytes)
}
return read_bytes;
}
/* }}} */
static char *sapi_cgibin_getenv(char *name, size_t name_len)
static char *sapi_cgibin_getenv(char *name, size_t name_len) /* {{{ */
{
/* if fpm has started, use fcgi env */
if (fpm_is_running) {
@@ -498,8 +517,9 @@ static char *sapi_cgibin_getenv(char *name, size_t name_len)
/* if fpm has not started yet, use std env */
return getenv(name);
}
/* }}} */
static char *_sapi_cgibin_putenv(char *name, char *value)
static char *_sapi_cgibin_putenv(char *name, char *value) /* {{{ */
{
int name_len;
@@ -511,15 +531,17 @@ static char *_sapi_cgibin_putenv(char *name, char *value)
fcgi_request *request = (fcgi_request*) SG(server_context);
return fcgi_putenv(request, name, name_len, value);
}
/* }}} */
static char *sapi_cgi_read_cookies(void)
static char *sapi_cgi_read_cookies(void) /* {{{ */
{
fcgi_request *request = (fcgi_request*) SG(server_context);
return FCGI_GETENV(request, "HTTP_COOKIE");
}
/* }}} */
static void cgi_php_load_env_var(char *var, unsigned int var_len, char *val, unsigned int val_len, void *arg)
static void cgi_php_load_env_var(char *var, unsigned int var_len, char *val, unsigned int val_len, void *arg) /* {{{ */
{
zval *array_ptr = (zval*)arg;
int filter_arg = (Z_ARR_P(array_ptr) == Z_ARR(PG(http_globals)[TRACK_VARS_ENV]))?PARSE_ENV:PARSE_SERVER;
@@ -529,13 +551,11 @@ static void cgi_php_load_env_var(char *var, unsigned int var_len, char *val, uns
php_register_variable_safe(var, val, new_val_len, array_ptr);
}
}
/* }}} */
void cgi_php_import_environment_variables(zval *array_ptr)
void cgi_php_import_environment_variables(zval *array_ptr) /* {{{ */
{
fcgi_request *request;
zend_string *var;
char *val;
int filter_arg;
if (Z_TYPE(PG(http_globals)[TRACK_VARS_ENV]) == IS_ARRAY &&
Z_ARR_P(array_ptr) != Z_ARR(PG(http_globals)[TRACK_VARS_ENV]) &&
@@ -559,8 +579,9 @@ void cgi_php_import_environment_variables(zval *array_ptr)
request = (fcgi_request*) SG(server_context);
fcgi_loadenv(request, cgi_php_load_env_var, array_ptr);
}
/* }}} */
static void sapi_cgi_register_variables(zval *track_vars_array)
static void sapi_cgi_register_variables(zval *track_vars_array) /* {{{ */
{
fcgi_request *request = (fcgi_request*) SG(server_context);
size_t php_self_len;
@@ -601,6 +622,7 @@ static void sapi_cgi_register_variables(zval *track_vars_array)
}
}
}
/* }}} */
/* {{{ sapi_cgi_log_fastcgi
*
@@ -713,7 +735,7 @@ static void php_cgi_ini_activate_user_config(char *path, int path_len, const cha
}
/* }}} */
static int sapi_cgi_activate(void)
static int sapi_cgi_activate(void) /* {{{ */
{
fcgi_request *request = (fcgi_request*) SG(server_context);
char *path, *doc_root, *server_name;
@@ -784,8 +806,9 @@ static int sapi_cgi_activate(void)
return SUCCESS;
}
/* }}} */
static int sapi_cgi_deactivate(void)
static int sapi_cgi_deactivate(void) /* {{{ */
{
/* flush only when SAPI was started. The reasons are:
1. SAPI Deactivate is called from two places: module init and request shutdown
@@ -802,14 +825,16 @@ static int sapi_cgi_deactivate(void)
}
return SUCCESS;
}
/* }}} */
static int php_cgi_startup(sapi_module_struct *sapi_module)
static int php_cgi_startup(sapi_module_struct *sapi_module) /* {{{ */
{
if (php_module_startup(sapi_module, &cgi_module_entry, 1) == FAILURE) {
return FAILURE;
}
return SUCCESS;
}
/* }}} */
/* {{{ sapi_module_struct cgi_sapi_module
*/
@@ -1360,6 +1385,14 @@ static void init_request_info(void)
}
/* }}} */
static void fpm_init_request(fcgi_request *req, int listen_fd) /* {{{ */ {
fcgi_init_request(req, listen_fd);
req->hook.on_accept = fpm_request_accepting;
req->hook.on_read = fpm_request_reading_headers;
req->hook.on_close = fpm_request_finished;
}
/* }}} */
static void fastcgi_ini_parser(zval *arg1, zval *arg2, zval *arg3, int callback_type, void *arg) /* {{{ */
{
int *mode = (int *)arg;
@@ -1523,7 +1556,7 @@ int main(int argc, char *argv[])
int max_requests = 500;
int requests = 0;
int fcgi_fd = 0;
fcgi_request *request;
fcgi_request request;
char *fpm_config = NULL;
char *fpm_prefix = NULL;
char *fpm_pid = NULL;
@@ -1553,6 +1586,7 @@ int main(int argc, char *argv[])
cgi_sapi_module.php_ini_path_override = NULL;
cgi_sapi_module.php_ini_ignore_cwd = 1;
fcgi_set_logger(fpm_fcgi_log);
fcgi_init();
#ifdef PHP_WIN32
@@ -1819,12 +1853,12 @@ consult the installation file that came with this distribution, or visit \n\
php_import_environment_variables = cgi_php_import_environment_variables;
/* library is already initialized, now init our request */
request = fcgi_init_request(fcgi_fd);
fpm_init_request(&request, fcgi_fd);
zend_first_try {
while (fcgi_accept_request(request) >= 0) {
while (fcgi_accept_request(&request) >= 0) {
request_body_fd = -1;
SG(server_context) = (void *) request;
SG(server_context) = (void *) &request;
init_request_info();
char *primary_script = NULL;
@@ -1833,7 +1867,7 @@ consult the installation file that came with this distribution, or visit \n\
/* request startup only after we've done all we can to
* get path_translated */
if (php_request_startup() == FAILURE) {
fcgi_finish_request(request, 1);
fcgi_finish_request(&request, 1);
SG(server_context) = NULL;
php_module_shutdown();
return FPM_EXIT_SOFTWARE;
@@ -1926,12 +1960,11 @@ fastcgi_request_done:
requests++;
if (max_requests && (requests == max_requests)) {
fcgi_finish_request(request, 1);
fcgi_finish_request(&request, 1);
break;
}
/* end of fastcgi loop */
}
fcgi_destroy_request(request);
fcgi_shutdown();
if (cgi_sapi_module.php_ini_path_override) {

View File

@@ -98,20 +98,17 @@ int zlog_set_level(int new_value) /* {{{ */
}
/* }}} */
void zlog_ex(const char *function, int line, int flags, const char *fmt, ...) /* {{{ */
void vzlog(const char *function, int line, int flags, const char *fmt, va_list args) /* {{{ */
{
struct timeval tv;
char buf[MAX_LINE_LENGTH];
const size_t buf_size = MAX_LINE_LENGTH;
va_list args;
size_t len = 0;
int truncated = 0;
int saved_errno;
if (external_logger) {
va_start(args, fmt);
len = vsnprintf(buf, buf_size, fmt, args);
va_end(args);
if (len >= buf_size) {
memcpy(buf + buf_size - sizeof("..."), "...", sizeof("...") - 1);
len = buf_size - 1;
@@ -157,9 +154,7 @@ void zlog_ex(const char *function, int line, int flags, const char *fmt, ...) /*
}
if (!truncated) {
va_start(args, fmt);
len += vsnprintf(buf + len, buf_size - len, fmt, args);
va_end(args);
if (len >= buf_size) {
truncated = 1;
}
@@ -197,3 +192,10 @@ void zlog_ex(const char *function, int line, int flags, const char *fmt, ...) /*
}
/* }}} */
void zlog_ex(const char *function, int line, int flags, const char *fmt, ...) /* {{{ */ {
va_list args;
va_start(args, fmt);
vzlog(function, line, flags, fmt, args);
va_end(args);
}
/* }}} */

View File

@@ -5,6 +5,8 @@
#ifndef ZLOG_H
#define ZLOG_H 1
#include <stdarg.h>
#define zlog(flags,...) zlog_ex(__func__, __LINE__, flags, __VA_ARGS__)
struct timeval;
@@ -17,6 +19,7 @@ void zlog_set_launched(void);
size_t zlog_print_time(struct timeval *tv, char *timebuf, size_t timebuf_len);
void vzlog(const char *function, int line, int flags, const char *fmt, va_list args);
void zlog_ex(const char *function, int line, int flags, const char *fmt, ...)
__attribute__ ((format(printf,4,5)));
@@ -24,6 +27,7 @@ void zlog_ex(const char *function, int line, int flags, const char *fmt, ...)
extern const int syslog_priorities[];
#endif
/* keep this same as FCGI_ERROR */
enum {
ZLOG_DEBUG = 1,
ZLOG_NOTICE = 2,