From 5b5e3a1ec19fe13b90ebe388b8b078760d8e2da5 Mon Sep 17 00:00:00 2001 From: "roberto@goyle" Date: Fri, 25 Nov 2011 15:34:41 +0100 Subject: [PATCH] added delta_requests --- master_utils.c | 3 ++ plugins/cgi/cgi_plugin.c | 56 +++++++++++++++++++++++++++++---- plugins/python/uwsgi_pymodule.c | 6 ++++ utils.c | 4 ++- uwsgi.c | 13 +++++--- uwsgi.h | 3 +- 6 files changed, 72 insertions(+), 13 deletions(-) diff --git a/master_utils.c b/master_utils.c index 8f1b50c1..41763f43 100644 --- a/master_utils.c +++ b/master_utils.c @@ -104,6 +104,8 @@ int uwsgi_respawn_worker(int wid) { uwsgi.workers[uwsgi.mywid].harakiri = 0; // do not reset worker counters on reload !!! //uwsgi.workers[uwsgi.mywid].requests = 0; + // ...but maintain a delta counter (yes this is racy in multithread) + uwsgi.workers[uwsgi.mywid].delta_requests = 0; //uwsgi.workers[uwsgi.mywid].failed_requests = 0; uwsgi.workers[uwsgi.mywid].respawn_count++; uwsgi.workers[uwsgi.mywid].last_spawn = uwsgi.current_time; @@ -330,6 +332,7 @@ void uwsgi_send_stats(int fd) { fprintf(output,"\"id\": %d, ", uwsgi.workers[i+1].id); fprintf(output,"\"pid\": %d, ", (int) uwsgi.workers[i+1].pid); stats_send_llu("\"requests\": %llu, ", uwsgi.workers[i+1].requests); + stats_send_llu("\"delta_requests\": %llu, ", uwsgi.workers[i+1].delta_requests); stats_send_llu("\"exceptions\": %llu, ", uwsgi.workers[i+1].exceptions); stats_send_llu("\"signals\": %llu, ", uwsgi.workers[i+1].signals); diff --git a/plugins/cgi/cgi_plugin.c b/plugins/cgi/cgi_plugin.c index c6575af1..70d21b93 100644 --- a/plugins/cgi/cgi_plugin.c +++ b/plugins/cgi/cgi_plugin.c @@ -6,7 +6,7 @@ extern struct uwsgi_server uwsgi; char *cgi_docroot; -#define LONG_ARGS_CGI_BASE 17000 + ((9 + 1) * 100) +#define LONG_ARGS_CGI_BASE 17000 + ((9 + 1) * 1000) #define LONG_ARGS_CGI LONG_ARGS_CGI_BASE + 1 struct option uwsgi_cgi_options[] = { @@ -32,6 +32,8 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) { int waitpid_status; char *argv[2]; char full_path[PATH_MAX]; + int cgi_pipe[2]; + ssize_t len; /* Standard CGI request */ if (!wsgi_req->uh.pktsize) { @@ -47,6 +49,26 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) { // check for file availability (and 'runnability') + char *path_info = uwsgi_concat4n(cgi_docroot, strlen(cgi_docroot), "/", 1,wsgi_req->path_info, wsgi_req->path_info_len, "", 0); + uwsgi_log("requested %s %s\n", path_info, realpath(path_info, full_path)); + + if (access(full_path, R_OK)) { + wsgi_req->status = 404; + wsgi_req->socket->proto_write(wsgi_req, "HTTP/1.1 404 Not Found\r\n\r\n", 26); + return UWSGI_OK; + } + + if (access(full_path, X_OK)) { + wsgi_req->status = 500; + wsgi_req->socket->proto_write(wsgi_req, "HTTP/1.1 500 Internal Server Error\r\n\r\n", 26); + return UWSGI_OK; + } + + if (pipe(cgi_pipe)) { + uwsgi_error("pipe()"); + return UWSGI_OK; + } + cgi_pid = fork(); if (cgi_pid < 0) { @@ -59,6 +81,29 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) { close(wsgi_req->poll.fd); wsgi_req->fd_closed = 1; + // wait for data + char startbuf[8]; + char *ptr = startbuf; + int remains = 8; + while(remains > 0) { + uwsgi_log("waiting for fd\n"); + int ret = uwsgi_waitfd(cgi_pipe[0], 10); + uwsgi_log("data available\n"); + if (ret > 0) { + len = read(cgi_pipe[0], ptr, remains); + if (len > 0) { + ptr+=len; + remains -= len; + } + } + } + + uwsgi_log("STARTBUF %.*s\n", 8, startbuf); + + if (!memcmp(startbuf, "Status: ", 8)) { + wsgi_req->socket->proto_write(wsgi_req, "HTTP/1.1 " + } + // now wait for fd if (waitpid(cgi_pid, &waitpid_status ,0) > 0) { uwsgi_log("CGI FINISHED\n"); @@ -69,18 +114,19 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) { // close all the fd except wsgi_req->poll.fd and 2; for(i=0;i< (int)uwsgi.max_fd;i++) { - if (i != wsgi_req->poll.fd && i != 2) { + if (i != wsgi_req->poll.fd && i != 2 && i != cgi_pipe[0] && i != cgi_pipe[1]) { close(i); } } - // now map wsgi_req->poll.fd to 0 && 1 + // now map wsgi_req->poll.fd to 0 & cgi_pipe[1] to 1 if (wsgi_req->poll.fd != 0) { dup2(wsgi_req->poll.fd, 0); close(wsgi_req->poll.fd); } - dup2(0,1); + uwsgi_log("mapping cgi_pipe %d to 1\n", cgi_pipe[1]); + dup2(cgi_pipe[1],1); // fill cgi env @@ -92,8 +138,6 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) { i++; } - char *path_info = uwsgi_concat4n(cgi_docroot, strlen(cgi_docroot), "/", 1,wsgi_req->path_info, wsgi_req->path_info_len, "", 0); - uwsgi_log("requested %s %s\n", path_info, realpath(path_info, full_path)); argv[0] = full_path; argv[1] = NULL; diff --git a/plugins/python/uwsgi_pymodule.c b/plugins/python/uwsgi_pymodule.c index 478309fb..2bdad70d 100644 --- a/plugins/python/uwsgi_pymodule.c +++ b/plugins/python/uwsgi_pymodule.c @@ -2490,6 +2490,12 @@ PyObject *py_uwsgi_workers(PyObject * self, PyObject * args) { } Py_DECREF(zero); + zero = PyLong_FromUnsignedLongLong(uwsgi.workers[i + 1].delta_requests); + if (PyDict_SetItemString(worker_dict, "delta_requests", zero)) { + goto clear; + } + Py_DECREF(zero); + zero = PyLong_FromUnsignedLongLong(uwsgi.workers[i + 1].signals); if (PyDict_SetItemString(worker_dict, "signals", zero)) { goto clear; diff --git a/utils.c b/utils.c index ca5b260e..da282f1d 100644 --- a/utils.c +++ b/utils.c @@ -665,6 +665,8 @@ void uwsgi_close_request(struct wsgi_request *wsgi_req) { } uwsgi.workers[0].requests++; uwsgi.workers[uwsgi.mywid].requests++; + // this is used for MAX_REQUESTS + uwsgi.workers[uwsgi.mywid].delta_requests++; // after_request hook if (uwsgi.p[wsgi_req->uh.modifier1]->after_request) @@ -700,7 +702,7 @@ void uwsgi_close_request(struct wsgi_request *wsgi_req) { memset(wsgi_req, 0, sizeof(struct wsgi_request)); wsgi_req->async_id = tmp_id; - if (uwsgi.shared->options[UWSGI_OPTION_MAX_REQUESTS] > 0 && uwsgi.workers[uwsgi.mywid].requests >= uwsgi.shared->options[UWSGI_OPTION_MAX_REQUESTS]) { + if (uwsgi.shared->options[UWSGI_OPTION_MAX_REQUESTS] > 0 && uwsgi.workers[uwsgi.mywid].delta_requests >= uwsgi.shared->options[UWSGI_OPTION_MAX_REQUESTS]) { goodbye_cruel_world(); } diff --git a/uwsgi.c b/uwsgi.c index 785ab9ad..ec0196f6 100644 --- a/uwsgi.c +++ b/uwsgi.c @@ -93,6 +93,7 @@ static struct option long_base_options[] = { {"emperor", required_argument, 0, LONG_ARGS_EMPEROR}, {"emperor-tyrant", no_argument, &uwsgi.emperor_tyrant, 1}, {"emperor-stats", required_argument, 0, LONG_ARGS_EMPEROR_STATS}, + {"emperor-stats-server", required_argument, 0, LONG_ARGS_EMPEROR_STATS}, {"early-emperor", no_argument, &uwsgi.early_emperor, 1}, {"emperor-broodlord", required_argument, 0, LONG_ARGS_EMPEROR_BROODLORD}, {"emperor-amqp-vhost", required_argument, 0, LONG_ARGS_EMPEROR_AMQP_VHOST}, @@ -196,6 +197,7 @@ static struct option long_base_options[] = { {"udp", required_argument, 0, LONG_ARGS_UDP}, #endif {"stats", required_argument, 0, LONG_ARGS_STATS}, + {"stats-server", required_argument, 0, LONG_ARGS_STATS}, #ifdef UWSGI_MULTICAST {"multicast", required_argument, 0, LONG_ARGS_MULTICAST}, {"cluster", required_argument, 0, LONG_ARGS_CLUSTER}, @@ -3826,17 +3828,17 @@ static int manage_base_opt(int i, char *optarg) { return 0; } -int manage_opt(int i, char *p) { +void manage_opt(int i, char *p) { int j; if (manage_base_opt(i, p)) { - return 1; + return; } for (j = 0; j < 0xFF; j++) { if (uwsgi.p[j]->manage_opt) { if (uwsgi.p[j]->manage_opt(i, p)) { - return 1; + return; } } } @@ -3844,12 +3846,13 @@ int manage_opt(int i, char *p) { for (j = 0; j < uwsgi.gp_cnt; j++) { if (uwsgi.gp[j]->manage_opt) { if (uwsgi.gp[j]->manage_opt(i, p)) { - return 1; + return; } } } - return 0; + // never here + exit(1); } void build_options() { diff --git a/uwsgi.h b/uwsgi.h index c4cb3812..c17a2578 100644 --- a/uwsgi.h +++ b/uwsgi.h @@ -1710,6 +1710,7 @@ struct uwsgi_worker { uint64_t respawn_count; uint64_t requests; + uint64_t delta_requests; uint64_t failed_requests; time_t harakiri; @@ -1855,7 +1856,7 @@ int uwsgi_parse_vars(struct wsgi_request *); int uwsgi_enqueue_message(char *, int, uint8_t, uint8_t, char *, int, int); -int manage_opt(int, char *); +void manage_opt(int, char *); void uwsgi_cluster_add_node(struct uwsgi_cluster_node *, int); int uwsgi_ping_node(int, struct wsgi_request *);