async sleep implementation, kqueue re-broken, profiler leaks memory

This commit is contained in:
roberto@sirius
2010-03-21 08:53:36 +01:00
parent 9cedbb6716
commit 9852b2fa62
13 changed files with 442 additions and 228 deletions
+87 -3
View File
@@ -31,6 +31,25 @@ int async_queue_init(int serverfd) {
return epfd;
}
int async_wait(int queuefd, void *events, int nevents, int block, int timeout) {
int ret ;
if (timeout <= 0) {
timeout = block;
}
else {
timeout = timeout*1000;
}
//fprintf(stderr,"waiting with timeout %d nevents %d\n", timeout, nevents);
ret = epoll_wait(queuefd, (struct epoll_event *) events, nevents, timeout);
if (ret < 0) {
perror("epoll_wait()");
}
return ret ;
}
int async_add(int queuefd, int fd, int etype) {
struct epoll_event ee;
@@ -83,6 +102,10 @@ int async_queue_init(int serverfd) {
return kfd;
}
int async_wait() {
uwsgi.async_nevents = kevent(uwsgi.async_queue, NULL, 0, uwsgi.async_events, uwsgi.async, &uwsgi.async_timeout);
}
int async_add(int queuefd, int fd, int etype) {
struct kevent kev;
@@ -117,14 +140,66 @@ struct wsgi_request *next_wsgi_req(struct uwsgi_server *uwsgi, struct wsgi_reque
return (struct wsgi_request *) ptr ;
}
int async_get_timeout(struct uwsgi_server *uwsgi) {
struct wsgi_request* wsgi_req = uwsgi->wsgi_requests ;
int i ;
time_t curtime, tdelta = 0 ;
int ret = 0 ;
if (!uwsgi->async_running) return 0;
for(i=0;i<uwsgi->async;i++) {
if (wsgi_req->async_status == UWSGI_AGAIN) {
if (wsgi_req->async_timeout_expired) {
return 0;
}
if (wsgi_req->async_timeout > 0) {
if (tdelta <= 0 || tdelta > wsgi_req->async_timeout) {
tdelta = wsgi_req->async_timeout ;
}
}
}
wsgi_req = next_wsgi_req(uwsgi, wsgi_req) ;
}
curtime = time(NULL);
ret = tdelta - curtime ;
if (ret > 0) {
return ret;
}
return 0;
}
void async_expire_timeouts(struct uwsgi_server *uwsgi) {
struct wsgi_request* wsgi_req = uwsgi->wsgi_requests ;
int i ;
time_t deadline = time(NULL);
for(i=0;i<uwsgi->async;i++) {
if (wsgi_req->async_status == UWSGI_AGAIN && wsgi_req->async_timeout > 0) {
if (wsgi_req->async_timeout <= deadline) {
wsgi_req->async_timeout = 0 ;
wsgi_req->async_timeout_expired = 1 ;
}
}
wsgi_req = next_wsgi_req(uwsgi, wsgi_req) ;
}
}
struct wsgi_request *find_first_available_wsgi_req(struct uwsgi_server *uwsgi) {
struct wsgi_request* wsgi_req = uwsgi->wsgi_requests ;
int i ;
for(i=0;i<uwsgi->async;i++) {
//fprintf(stderr,"request %d fd %d switches %d\n", i, wsgi_req->poll.fd, wsgi_req->async_switches);
if (wsgi_req->async_status == 0) {
if (wsgi_req->async_status == UWSGI_OK) {
return wsgi_req ;
}
wsgi_req = next_wsgi_req(uwsgi, wsgi_req) ;
@@ -149,6 +224,13 @@ struct wsgi_request *find_wsgi_req_by_fd(struct uwsgi_server *uwsgi, int fd, int
}
void async_set_timeout(struct wsgi_request *wsgi_req, time_t timeout) {
wsgi_req->async_timeout = time(NULL);
wsgi_req->async_timeout += timeout;
wsgi_req->async_timeout_expired = 0 ;
}
struct wsgi_request * async_loop(struct uwsgi_server *uwsgi) {
@@ -173,12 +255,14 @@ struct wsgi_request * async_loop(struct uwsgi_server *uwsgi) {
wsgi_req->async_waiting_fd_monitored = 1;
wsgi_req->async_status = UWSGI_AGAIN;
}
else if (wsgi_req->async_waiting_fd == -1) {
else if (wsgi_req->async_waiting_fd == -1 && wsgi_req->async_timeout <= 0) {
uwsgi->async_running = 0 ;
// st global wsgi_req for python functions
uwsgi->wsgi_req = wsgi_req ;
wsgi_req->async_status = (*uwsgi->shared->hooks[wsgi_req->modifier]) (uwsgi, wsgi_req);
wsgi_req->async_switches++;
if (wsgi_req->async_status < UWSGI_AGAIN) {
return wsgi_req;
}
+17 -17
View File
@@ -319,8 +319,8 @@ int uwsgi_parse_vars(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req)
ptrbuf += 2;
if (ptrbuf + strsize < bufferend) {
// var key
uwsgi->hvec[wsgi_req->var_cnt].iov_base = ptrbuf;
uwsgi->hvec[wsgi_req->var_cnt].iov_len = strsize;
wsgi_req->hvec[wsgi_req->var_cnt].iov_base = ptrbuf;
wsgi_req->hvec[wsgi_req->var_cnt].iov_len = strsize;
ptrbuf += strsize;
if (ptrbuf + 2 < bufferend) {
memcpy(&strsize, ptrbuf, 2);
@@ -329,56 +329,56 @@ int uwsgi_parse_vars(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req)
#endif
ptrbuf += 2;
if (ptrbuf + strsize <= bufferend) {
if (!strncmp("SCRIPT_NAME", uwsgi->hvec[wsgi_req->var_cnt].iov_base, uwsgi->hvec[wsgi_req->var_cnt].iov_len)) {
if (!strncmp("SCRIPT_NAME", wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->script_name = ptrbuf;
wsgi_req->script_name_len = strsize;
}
else if (!strncmp("SERVER_PROTOCOL", uwsgi->hvec[wsgi_req->var_cnt].iov_base, uwsgi->hvec[wsgi_req->var_cnt].iov_len)) {
else if (!strncmp("SERVER_PROTOCOL", wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->protocol = ptrbuf;
wsgi_req->protocol_len = strsize;
}
else if (!strncmp("REQUEST_URI", uwsgi->hvec[wsgi_req->var_cnt].iov_base, uwsgi->hvec[wsgi_req->var_cnt].iov_len)) {
else if (!strncmp("REQUEST_URI", wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->uri = ptrbuf;
wsgi_req->uri_len = strsize;
}
else if (!strncmp("QUERY_STRING", uwsgi->hvec[wsgi_req->var_cnt].iov_base, uwsgi->hvec[wsgi_req->var_cnt].iov_len)) {
else if (!strncmp("QUERY_STRING", wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->query_string = ptrbuf;
wsgi_req->query_string_len = strsize;
}
else if (!strncmp("REQUEST_METHOD", uwsgi->hvec[wsgi_req->var_cnt].iov_base, uwsgi->hvec[wsgi_req->var_cnt].iov_len)) {
else if (!strncmp("REQUEST_METHOD", wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->method = ptrbuf;
wsgi_req->method_len = strsize;
}
else if (!strncmp("REMOTE_ADDR", uwsgi->hvec[wsgi_req->var_cnt].iov_base, uwsgi->hvec[wsgi_req->var_cnt].iov_len)) {
else if (!strncmp("REMOTE_ADDR", wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->remote_addr = ptrbuf;
wsgi_req->remote_addr_len = strsize;
}
else if (!strncmp("REMOTE_USER", uwsgi->hvec[wsgi_req->var_cnt].iov_base, uwsgi->hvec[wsgi_req->var_cnt].iov_len)) {
else if (!strncmp("REMOTE_USER", wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->remote_user = ptrbuf;
wsgi_req->remote_user_len = strsize;
}
else if (!strncmp("UWSGI_SCHEME", uwsgi->hvec[wsgi_req->var_cnt].iov_base, uwsgi->hvec[wsgi_req->var_cnt].iov_len)) {
else if (!strncmp("UWSGI_SCHEME", wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->scheme = ptrbuf;
wsgi_req->scheme_len = strsize;
}
else if (!strncmp("UWSGI_SCRIPT",uwsgi->hvec[wsgi_req->var_cnt].iov_base, uwsgi->hvec[wsgi_req->var_cnt].iov_len )) {
else if (!strncmp("UWSGI_SCRIPT",wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len )) {
wsgi_req->wsgi_script = ptrbuf;
wsgi_req->wsgi_script_len = strsize;
}
else if (!strncmp("UWSGI_MODULE", uwsgi->hvec[wsgi_req->var_cnt].iov_base, uwsgi->hvec[wsgi_req->var_cnt].iov_len)) {
else if (!strncmp("UWSGI_MODULE", wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->wsgi_module = ptrbuf;
wsgi_req->wsgi_module_len = strsize;
}
else if (!strncmp("UWSGI_CALLABLE", uwsgi->hvec[wsgi_req->var_cnt].iov_base, uwsgi->hvec[wsgi_req->var_cnt].iov_len)) {
else if (!strncmp("UWSGI_CALLABLE", wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->wsgi_callable = ptrbuf;
wsgi_req->wsgi_callable_len = strsize;
}
else if (!strncmp("HTTPS", uwsgi->hvec[wsgi_req->var_cnt].iov_base, uwsgi->hvec[wsgi_req->var_cnt].iov_len)) {
else if (!strncmp("HTTPS", wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->https = ptrbuf;
wsgi_req->https_len = strsize;
}
#ifdef UNBIT
else if (!strncmp("UNBIT_FLAGS", uwsgi->hvec[wsgi_req->var_cnt].iov_base, uwsgi->hvec[wsgi_req->var_cnt].iov_len)) {
else if (!strncmp("UNBIT_FLAGS", wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->unbit_flags = *(unsigned long long *) ptrbuf;
}
#endif
@@ -390,8 +390,8 @@ int uwsgi_parse_vars(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req)
return -1;
}
// var value
uwsgi->hvec[wsgi_req->var_cnt].iov_base = ptrbuf;
uwsgi->hvec[wsgi_req->var_cnt].iov_len = strsize;
wsgi_req->hvec[wsgi_req->var_cnt].iov_base = ptrbuf;
wsgi_req->hvec[wsgi_req->var_cnt].iov_len = strsize;
if (wsgi_req->var_cnt < uwsgi->vec_size - (4 + 1)) {
wsgi_req->var_cnt++;
}
+120
View File
@@ -0,0 +1,120 @@
#include "uwsgi.h"
int manage_python_response(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
PyObject *pychunk ;
ssize_t wsize ;
// return or yield ?
if (PyString_Check(wsgi_req->async_result)) {
//fprintf(stderr,"DOH !!!\n");
if ((wsize = write(wsgi_req->poll.fd, PyString_AsString(wsgi_req->async_result), PyString_Size(wsgi_req->async_result))) < 0) {
perror("write()");
goto clear;
}
wsgi_req->response_size += wsize;
goto clear;
}
// ok its a yield
if (!wsgi_req->async_placeholder) {
wsgi_req->async_placeholder = PyObject_GetIter(wsgi_req->async_result);
if (!wsgi_req->async_placeholder) {
goto clear2;
}
Py_DECREF(wsgi_req->async_result);
#ifdef UWSGI_ASYNC
if (uwsgi->async > 1) {
return UWSGI_AGAIN;
}
#endif
}
/*
boh = wsgi_req->async_placeholder; boh2 = wsgi_req->async_result ;
fprintf(stderr,"placeholder refcnt %d: %d\n", wsgi_req->async_switches, boh->ob_refcnt);
*/
//fprintf(stderr,"NEXT CHUNK\n");
pychunk = PyIter_Next(wsgi_req->async_placeholder) ;
/*
boh = wsgi_req->async_placeholder; boh2 = wsgi_req->async_result ;
fprintf(stderr,"AFTER NEXT %d/%d\n", boh->ob_refcnt, boh2->ob_refcnt);
*/
if (!pychunk) {
//fprintf(stderr,"AIA\n");
if (PyErr_Occurred()) PyErr_Print();
goto clear;
}
//fprintf(stderr,"ob type %s\n", pychunk->ob_type->tp_name);
if (PyString_Check(pychunk)) {
if ((wsize = write(wsgi_req->poll.fd, PyString_AsString(pychunk), PyString_Size(pychunk))) < 0) {
perror("write()");
Py_DECREF(pychunk);
goto clear;
}
wsgi_req->response_size += wsize;
}
Py_DECREF(pychunk);
//Py_DECREF(wsgi_req->async_placeholder);
//Py_DECREF(wsgi_req->async_result);
/*
boh = wsgi_req->async_placeholder; boh2 = wsgi_req->async_result ;
fprintf(stderr,"AFTER CHUNK %d/%d\n", boh->ob_refcnt, boh2->ob_refcnt);
*/
return UWSGI_AGAIN ;
clear:
//fprintf(stderr,"finito\n");
if (wsgi_req->async_environ) {
PyDict_Clear(wsgi_req->async_environ);
}
if (wsgi_req->async_post) {
fclose(wsgi_req->async_post);
}
Py_XDECREF(wsgi_req->async_placeholder);
clear2:
Py_DECREF(wsgi_req->async_result);
//fprintf(stderr,"RESULT REFCNT: %d\n", ((PyObject *) wsgi_req->async_result)->ob_refcnt);
PyErr_Clear();
return UWSGI_OK;
}
PyObject *python_call(PyObject *callable, PyObject *args) {
PyObject *pyret;
pyret = PyEval_CallObject(callable, args);
if (PyErr_Occurred()) {
PyErr_Print();
}
return pyret;
}
int uwsgi_python_call(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req, PyObject *callable, PyObject *args) {
wsgi_req->async_result = python_call(callable, args);
if (wsgi_req->async_result) {
while ( manage_python_response(uwsgi, wsgi_req) != UWSGI_OK) {
#ifdef UWSGI_ASYNC
if (uwsgi->async > 1) {
return UWSGI_AGAIN;
}
#endif
}
}
return UWSGI_OK;
}
+1 -1
View File
@@ -1,3 +1,3 @@
def application(env, start_response):
start_response('200 Ok', [('Content-type', 'text/plain; charset=UTF-32')])
start_response('200 Ok', [('Content-type', 'text/plain')])
return "hello world"
+3 -2
View File
@@ -1,5 +1,6 @@
import time
def application(env, start_response):
start_response( '200 OK', [ ('Content-Type','text/html') ])
for i in range(1,10000):
yield "<h1>%s</h1>" % i
for i in range(1,100000):
yield "<h1>%s at %s</h1>" % (i, str(time.time()))
+9
View File
@@ -0,0 +1,9 @@
import uwsgi
sleepvalue = 5 ;
def application(env, start_response):
start_response('200 Ok', [('Content-type', 'text/html')])
yield uwsgi.async_sleep(sleepvalue)
#print "TIMEOUT: ", env['x-wsgiorg.fdevent.timeout']
yield "<h1>Hello World after %d seconds</h1>" % sleepvalue
+2 -1
View File
@@ -1,4 +1,5 @@
def application(environ, start_response):
start_response('200 OK', [('Content-Type', 'image/png')])
fd = open('logo_uWSGI.png','r')
return environ['wsgi.file_wrapper'](fd, 4096)
yield environ['wsgi.file_wrapper'](fd, 4096)
+100 -60
View File
@@ -301,43 +301,43 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
if (uwsgi.wsgi_req->protocol_len == 0) {
uwsgi.hvec[0].iov_base = (char *) http_protocol;
uwsgi.wsgi_req->hvec[0].iov_base = (char *) http_protocol;
uwsgi.wsgi_req->protocol_len = 8;
}
else {
uwsgi.hvec[0].iov_base = uwsgi.wsgi_req->protocol;
uwsgi.wsgi_req->hvec[0].iov_base = uwsgi.wsgi_req->protocol;
}
uwsgi.hvec[0].iov_len = uwsgi.wsgi_req->protocol_len;
uwsgi.hvec[1].iov_base = " ";
uwsgi.hvec[1].iov_len = 1;
uwsgi.wsgi_req->hvec[0].iov_len = uwsgi.wsgi_req->protocol_len;
uwsgi.wsgi_req->hvec[1].iov_base = " ";
uwsgi.wsgi_req->hvec[1].iov_len = 1;
#ifdef PYTHREE
uwsgi.hvec[2].iov_base = PyBytes_AsString(PyUnicode_AsASCIIString(head));
uwsgi.hvec[2].iov_len = strlen(uwsgi.hvec[2].iov_base);
uwsgi.wsgi_req->hvec[2].iov_base = PyBytes_AsString(PyUnicode_AsASCIIString(head));
uwsgi.wsgi_req->hvec[2].iov_len = strlen(uwsgi.wsgi_req->hvec[2].iov_base);
#else
uwsgi.hvec[2].iov_base = PyString_AsString(head);
uwsgi.hvec[2].iov_len = PyString_Size(head);
uwsgi.wsgi_req->hvec[2].iov_base = PyString_AsString(head);
uwsgi.wsgi_req->hvec[2].iov_len = PyString_Size(head);
#endif
uwsgi.wsgi_req->status = atoi(uwsgi.hvec[2].iov_base);
uwsgi.hvec[3].iov_base = nl;
uwsgi.hvec[3].iov_len = NL_SIZE;
uwsgi.wsgi_req->status = atoi(uwsgi.wsgi_req->hvec[2].iov_base);
uwsgi.wsgi_req->hvec[3].iov_base = nl;
uwsgi.wsgi_req->hvec[3].iov_len = NL_SIZE;
#ifndef UNBIT
}
else {
// drop http status on cgi mode
base = 3;
uwsgi.hvec[0].iov_base = "Status: ";
uwsgi.hvec[0].iov_len = 8;
uwsgi.wsgi_req->hvec[0].iov_base = "Status: ";
uwsgi.wsgi_req->hvec[0].iov_len = 8;
#ifdef PYTHREE
uwsgi.hvec[1].iov_base = PyBytes_AsString(PyUnicode_AsASCIIString(head));
uwsgi.hvec[1].iov_len = strlen(uwsgi.hvec[1].iov_base);
uwsgi.wsgi_req->hvec[1].iov_base = PyBytes_AsString(PyUnicode_AsASCIIString(head));
uwsgi.wsgi_req->hvec[1].iov_len = strlen(uwsgi.wsgi_req->hvec[1].iov_base);
#else
uwsgi.hvec[1].iov_base = PyString_AsString(head);
uwsgi.hvec[1].iov_len = PyString_Size(head);
uwsgi.wsgi_req->hvec[1].iov_base = PyString_AsString(head);
uwsgi.wsgi_req->hvec[1].iov_len = PyString_Size(head);
#endif
uwsgi.wsgi_req->status = atoi(uwsgi.hvec[1].iov_base);
uwsgi.hvec[2].iov_base = nl;
uwsgi.hvec[2].iov_len = NL_SIZE;
uwsgi.wsgi_req->status = atoi(uwsgi.wsgi_req->hvec[1].iov_base);
uwsgi.wsgi_req->hvec[2].iov_base = nl;
uwsgi.wsgi_req->hvec[2].iov_len = NL_SIZE;
}
#endif
@@ -385,31 +385,31 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
goto clear;
}
#ifdef PYTHREE
uwsgi.hvec[j].iov_base = PyBytes_AsString(PyUnicode_AsASCIIString(h_key));
uwsgi.hvec[j].iov_len = strlen(uwsgi.hvec[j].iov_base);
uwsgi.wsgi_req->hvec[j].iov_base = PyBytes_AsString(PyUnicode_AsASCIIString(h_key));
uwsgi.wsgi_req->hvec[j].iov_len = strlen(uwsgi.wsgi_req->hvec[j].iov_base);
#else
uwsgi.hvec[j].iov_base = PyString_AsString(h_key);
uwsgi.hvec[j].iov_len = PyString_Size(h_key);
uwsgi.wsgi_req->hvec[j].iov_base = PyString_AsString(h_key);
uwsgi.wsgi_req->hvec[j].iov_len = PyString_Size(h_key);
#endif
uwsgi.hvec[j + 1].iov_base = h_sep;
uwsgi.hvec[j + 1].iov_len = H_SEP_SIZE;
uwsgi.wsgi_req->hvec[j + 1].iov_base = h_sep;
uwsgi.wsgi_req->hvec[j + 1].iov_len = H_SEP_SIZE;
#ifdef PYTHREE
uwsgi.hvec[j + 2].iov_base = PyBytes_AsString(PyUnicode_AsASCIIString(h_value));
uwsgi.hvec[j + 2].iov_len = strlen(uwsgi.hvec[j + 2].iov_base);
uwsgi.wsgi_req->hvec[j + 2].iov_base = PyBytes_AsString(PyUnicode_AsASCIIString(h_value));
uwsgi.wsgi_req->hvec[j + 2].iov_len = strlen(uwsgi.wsgi_req->hvec[j + 2].iov_base);
#else
uwsgi.hvec[j + 2].iov_base = PyString_AsString(h_value);
uwsgi.hvec[j + 2].iov_len = PyString_Size(h_value);
uwsgi.wsgi_req->hvec[j + 2].iov_base = PyString_AsString(h_value);
uwsgi.wsgi_req->hvec[j + 2].iov_len = PyString_Size(h_value);
#endif
uwsgi.hvec[j + 3].iov_base = nl;
uwsgi.hvec[j + 3].iov_len = NL_SIZE;
//fprintf(stderr, "%.*s: %.*s\n", uwsgi.hvec[j].iov_len, (char *)uwsgi.hvec[j].iov_base, uwsgi.hvec[j+2].iov_len, (char *) uwsgi.hvec[j+2].iov_base);
uwsgi.wsgi_req->hvec[j + 3].iov_base = nl;
uwsgi.wsgi_req->hvec[j + 3].iov_len = NL_SIZE;
//fprintf(stderr, "%.*s: %.*s\n", uwsgi.wsgi_req->hvec[j].iov_len, (char *)uwsgi.wsgi_req->hvec[j].iov_base, uwsgi.wsgi_req->hvec[j+2].iov_len, (char *) uwsgi.wsgi_req->hvec[j+2].iov_base);
}
#ifdef UNBIT
if (save_to_disk >= 0) {
for (j = 0; j < i; j += 4) {
if (!strncasecmp(uwsgi.hvec[j].iov_base, "Set-Cookie", uwsgi.hvec[j].iov_len)) {
if (!strncasecmp(uwsgi.wsgi_req->hvec[j].iov_base, "Set-Cookie", uwsgi.wsgi_req->hvec[j].iov_len)) {
close(save_to_disk);
save_to_disk = -1;
break;
@@ -420,10 +420,10 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
// \r\n
j = (i * 4) + base;
uwsgi.hvec[j].iov_base = nl;
uwsgi.hvec[j].iov_len = NL_SIZE;
uwsgi.wsgi_req->hvec[j].iov_base = nl;
uwsgi.wsgi_req->hvec[j].iov_len = NL_SIZE;
uwsgi.wsgi_req->headers_size = writev(uwsgi.wsgi_req->poll.fd, uwsgi.hvec, j + 1);
uwsgi.wsgi_req->headers_size = writev(uwsgi.wsgi_req->poll.fd, uwsgi.wsgi_req->hvec, j + 1);
if (uwsgi.wsgi_req->headers_size < 0) {
perror("writev()");
}
@@ -515,6 +515,10 @@ int main(int argc, char *argv[], char *envp[]) {
int rlen;
#ifdef UWSGI_ASYNC
int current_async_timeout = 0;
#endif
#ifdef UWSGI_NAGIOS
int nagios = 0;
#endif
@@ -844,7 +848,6 @@ int main(int argc, char *argv[], char *envp[]) {
fprintf(stderr, "allocated %d bytes for %d request's buffer.\n", uwsgi.buffer_size, uwsgi.async);
if (uwsgi.synclog) {
fprintf(stderr, "allocating a memory page for synced logging.\n");
uwsgi.sync_page = malloc(uwsgi.page_size);
@@ -1600,8 +1603,8 @@ int main(int argc, char *argv[], char *envp[]) {
uwsgi.hvec = malloc(sizeof(struct iovec) * uwsgi.vec_size);
if (uwsgi.hvec == NULL) {
uwsgi.async_hvec = malloc((sizeof(struct iovec) * uwsgi.vec_size)*uwsgi.async);
if (uwsgi.async_hvec == NULL) {
fprintf(stderr, "unable to allocate memory for iovec.\n");
exit(1);
}
@@ -1665,21 +1668,16 @@ int main(int argc, char *argv[], char *envp[]) {
#ifdef UWSGI_ASYNC
if (uwsgi.async > 1) {
#ifdef __linux__
uwsgi.async_nevents = epoll_wait(uwsgi.async_queue, uwsgi.async_events, uwsgi.async, uwsgi.async_running);
#elif defined(__sun__)
#else
if (uwsgi.async_running == 0) {
uwsgi.async_nevents = kevent(uwsgi.async_queue, NULL, 0, uwsgi.async_events, uwsgi.async, &uwsgi.async_timeout);
}
else {
uwsgi.async_nevents = kevent(uwsgi.async_queue, NULL, 0, uwsgi.async_events, uwsgi.async, NULL);
}
#endif
current_async_timeout = async_get_timeout(&uwsgi) ;
fprintf(stderr,"sleeping for %d secs\n", current_async_timeout);
uwsgi.async_nevents = async_wait(uwsgi.async_queue, uwsgi.async_events, uwsgi.async, uwsgi.async_running, current_async_timeout);
async_expire_timeouts(&uwsgi);
if (uwsgi.async_nevents < 0) {
perror("epoll_wait()");
continue;
}
for(i=0; i<uwsgi.async_nevents;i++) {
if (uwsgi.async_events[i].ASYNC_FD == uwsgi.serverfd) {
@@ -1697,8 +1695,10 @@ int main(int argc, char *argv[], char *envp[]) {
uwsgi.wsgi_req->sendfile_fd = -1;
#endif
uwsgi.wsgi_req->async_id = ( (uint8_t *) uwsgi.wsgi_req - (uint8_t *) uwsgi.wsgi_requests)/(sizeof(struct wsgi_request)+(uwsgi.buffer_size-1)) ;
uwsgi.wsgi_req->hvec = &uwsgi.async_hvec[uwsgi.wsgi_req->async_id];
uwsgi.wsgi_req->poll.fd = accept(uwsgi.serverfd, (struct sockaddr *) &c_addr, (socklen_t *) & c_len);
fprintf(stderr,"accepted request\n");
if (uwsgi.wsgi_req->poll.fd < 0) {
perror("accept()");
@@ -1720,6 +1720,9 @@ int main(int argc, char *argv[], char *envp[]) {
}
uwsgi.wsgi_req->async_status = (*uwsgi.shared->hooks[uwsgi.wsgi_req->modifier]) (&uwsgi, uwsgi.wsgi_req);
if (uwsgi.wsgi_req->async_status == UWSGI_OK) {
goto reqclear;
}
}
else {
@@ -1748,9 +1751,11 @@ cycle:
uwsgi.wsgi_req->poll.events = POLLIN;
uwsgi.wsgi_req->app_id = uwsgi.default_app;
uwsgi.wsgi_req->async_id = 0;
#ifdef UWSGI_SENDFILE
uwsgi.wsgi_req->sendfile_fd = -1;
#endif
uwsgi.wsgi_req->hvec = &uwsgi.async_hvec[uwsgi.wsgi_req->async_id];
uwsgi.wsgi_req->poll.fd = accept(uwsgi.serverfd, (struct sockaddr *) &c_addr, (socklen_t *) & c_len);
@@ -1780,6 +1785,9 @@ cycle:
}
#endif
reqclear:
gettimeofday(&uwsgi.wsgi_req->end_of_request, NULL);
uwsgi.workers[uwsgi.mywid].running_time += (double) (((double) (uwsgi.wsgi_req->end_of_request.tv_sec * 1000000 + uwsgi.wsgi_req->end_of_request.tv_usec) - (double) (uwsgi.wsgi_req->start_of_request.tv_sec * 1000000 + uwsgi.wsgi_req->start_of_request.tv_usec)) / (double) 1000.0);
@@ -1884,6 +1892,9 @@ int init_uwsgi_app(PyObject * force_wsgi_dict, PyObject * my_callable) {
PyObject *pycprof, *pycprof_dict;
char tmpstring[256];
int id;
#ifdef UWSGI_ASYNC
int i;
#endif
struct uwsgi_app *wi;
@@ -2030,6 +2041,40 @@ int init_uwsgi_app(PyObject * force_wsgi_dict, PyObject * my_callable) {
return -1;
}
#ifdef UWSGI_ASYNC
wi->wsgi_environ = malloc(sizeof(PyObject*)*uwsgi.async);
if (!wi->wsgi_environ) {
perror("malloc()");
if (uwsgi.single_interpreter == 0) {
Py_EndInterpreter(wi->interpreter);
PyThreadState_Swap(uwsgi.main_thread) ;
}
return -1 ;
}
for(i=0;i<uwsgi.async;i++) {
wi->wsgi_environ[i] = PyDict_New();
// this will leak all the already allocated dictionary !!!
if (!wi->wsgi_environ[i]) {
if (uwsgi.single_interpreter == 0) {
Py_EndInterpreter(wi->interpreter);
PyThreadState_Swap(uwsgi.main_thread) ;
}
return -1 ;
}
}
#else
wi->wsgi_environ = PyDict_New();
if (!wi->wsgi_environ) {
PyErr_Print();
if (uwsgi.single_interpreter == 0) {
Py_EndInterpreter(wi->interpreter);
PyThreadState_Swap(uwsgi.main_thread) ;
}
return -1 ;
}
#endif
if (wsgi_dict) {
wi->wsgi_harakiri = PyDict_GetItemString(wsgi_dict, "harakiri");
@@ -2056,12 +2101,7 @@ int init_uwsgi_app(PyObject * force_wsgi_dict, PyObject * my_callable) {
PyErr_Print();
exit(1);
}
/*
if (PyDict_SetItem(wi->pymain_dict, PyString_FromFormat("uwsgi_environ__%d", id), wi->wsgi_environ)) {
PyErr_Print();
exit(1);
}
*/
if (PyDict_SetItem(wi->pymain_dict, PyString_FromFormat("uwsgi_spit__%d", id), wsgi_spitout)) {
PyErr_Print();
exit(1);
+23 -3
View File
@@ -207,6 +207,12 @@ struct uwsgi_app {
PyObject *wsgi_callable;
PyObject *wsgi_args;
#ifdef UWSGI_ASYNC
PyObject **wsgi_environ;
#else
PyObject *wsgi_environ;
#endif
PyObject *wsgi_harakiri;
PyObject *wsgi_sendfile;
@@ -231,6 +237,8 @@ struct __attribute__ ((packed)) wsgi_request {
struct pollfd poll;
// iovec
struct iovec *hvec;
struct timeval start_of_request;
struct timeval end_of_request;
@@ -274,12 +282,16 @@ struct __attribute__ ((packed)) wsgi_request {
int response_size;
int headers_size;
int async_id;
int async_status ;
int async_waiting_fd;
int async_waiting_fd_type;
int async_waiting_fd_monitored;
int async_switches;
time_t async_timeout ;
int async_timeout_expired ;
void *async_app;
void *async_result;
void *async_placeholder;
@@ -317,6 +329,8 @@ struct uwsgi_server {
char *proxy_socket_name;
#endif
struct iovec *async_hvec;
struct rlimit rl;
char *binary_path;
@@ -335,8 +349,6 @@ struct uwsgi_server {
char *snmp_community;
#endif
// iovec
struct iovec *hvec;
int to_heaven;
int to_hell;
@@ -367,7 +379,6 @@ struct uwsgi_server {
#elif defined(__sun__)
#else
struct kevent *async_events;
struct timespec async_timeout;
#endif
int max_vars;
@@ -637,9 +648,14 @@ struct wsgi_request *find_first_available_wsgi_req(struct uwsgi_server *);
struct wsgi_request *find_wsgi_req_by_fd(struct uwsgi_server *, int, int);
int async_add(int, int , int) ;
int async_wait(int, void *, int, int, int);
int async_del(int, int , int) ;
int async_queue_init(int);
int async_get_timeout(struct uwsgi_server *);
void async_set_timeout(struct wsgi_request *, time_t);
void async_expire_timeouts(struct uwsgi_server *);
#ifdef __linux__
#define ASYNC_FD data.fd
#define ASYNC_EV events
@@ -649,3 +665,7 @@ int async_queue_init(int);
#define ASYNC_EV filter
#endif
#endif
int manage_python_response(struct uwsgi_server *, struct wsgi_request *);
int uwsgi_python_call(struct uwsgi_server *, struct wsgi_request *, PyObject *, PyObject *);
PyObject *python_call(PyObject *, PyObject *);
+12 -23
View File
@@ -46,38 +46,27 @@ int uwsgi_request_admin(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_re
perror("write()");
}
return 0;
return UWSGI_OK;
}
/* uwsgi FASTFUNC|26 */
int uwsgi_request_fastfunc(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
PyObject *zero, *func_result, *fchunk, *func_chunks;
PyObject *ffunc;
zero = PyList_GetItem(uwsgi->fastfuncslist, wsgi_req->modifier_arg);
if (zero) {
#ifdef UWSGI_ASYNC
if (wsgi_req->async_status == UWSGI_AGAIN) {
return manage_python_response(uwsgi, wsgi_req);
}
#endif
ffunc = PyList_GetItem(uwsgi->fastfuncslist, wsgi_req->modifier_arg);
if (ffunc) {
fprintf(stderr, "managing fastfunc %d\n", wsgi_req->modifier_arg);
func_result = PyEval_CallObject(zero, NULL);
if (PyErr_Occurred()) {
PyErr_Print();
}
if (func_result) {
func_chunks = PyObject_GetIter(func_result);
if (func_chunks) {
while ((fchunk = PyIter_Next(func_chunks))) {
if (PyString_Check(fchunk)) {
wsgi_req->response_size += write(wsgi_req->poll.fd, PyString_AsString(fchunk), PyString_Size(fchunk));
}
Py_DECREF(fchunk);
}
Py_DECREF(func_chunks);
}
Py_DECREF(func_result);
}
return uwsgi_python_call(uwsgi, wsgi_req, ffunc, NULL);
}
PyErr_Clear();
return 0;
return UWSGI_OK;
}
/* uwsgi MARSHAL|33 */
+24
View File
@@ -19,6 +19,27 @@ extern struct uwsgi_server uwsgi;
#define UWSGI_LOGBASE "[- uWSGI -"
#ifdef UWSGI_ASYNC
PyObject *py_uwsgi_async_sleep(PyObject * self, PyObject * args) {
float timeout ;
time_t sec_timeout ;
if (!PyArg_ParseTuple(args, "f:async_sleep", &timeout)) {
return NULL;
}
sec_timeout = (time_t) timeout ;
fprintf(stderr,"timeout sleep: %d\n", (int) sec_timeout);
if (sec_timeout > 0) {
async_set_timeout(uwsgi.wsgi_req, sec_timeout);
}
return PyString_FromString("") ;
}
#endif
PyObject *py_uwsgi_warning(PyObject * self, PyObject * args) {
char *message;
int len;
@@ -831,6 +852,9 @@ static PyMethodDef uwsgi_advanced_methods[] = {
{"set_warning_message", py_uwsgi_warning, METH_VARARGS, ""},
#ifdef UWSGI_MULTICAST
{"send_multicast_message", py_uwsgi_multicast, METH_VARARGS, ""},
#endif
#ifdef UWSGI_ASYNC
{"async_sleep", py_uwsgi_async_sleep, METH_VARARGS, ""},
#endif
//{"call_hook", py_uwsgi_call_hook, METH_VARARGS, ""},
{NULL, NULL},
+1 -1
View File
@@ -30,7 +30,7 @@ uwsgi_os = os.uname()[0]
import sys
import subprocess
gcc_list = ['utils', 'protocol', 'socket', 'logging', 'wsgi_handlers', 'uwsgi_handlers', 'uwsgi']
gcc_list = ['utils', 'pyutils', 'protocol', 'socket', 'logging', 'wsgi_handlers', 'uwsgi_handlers', 'uwsgi']
# large file support
cflags = ['-D_LARGEFILE_SOURCE', '-D_FILE_OFFSET_BITS=64']
+43 -117
View File
@@ -2,86 +2,29 @@
static int uwsgi_sendfile(struct uwsgi_server *, int, int);
static PyObject *wsgi_response(PyObject *chunks, struct wsgi_request *wsgi_req) {
PyObject *wchunk ;
ssize_t wsize ;
wchunk = PyIter_Next(chunks) ;
if (!wchunk) {
if (PyErr_Occurred())
PyErr_Print();
return NULL;
}
if (PyString_Check(wchunk)) {
if ((wsize = write(wsgi_req->poll.fd, PyString_AsString(wchunk), PyString_Size(wchunk))) < 0) {
perror("write()");
return NULL;
}
wsgi_req->response_size += wsize;
#ifdef UNBIT
if (save_to_disk >= 0) {
if (write(save_to_disk, PyString_AsString(wchunk), PyString_Size(wchunk)) < 0) {
perror("write()");
close(save_to_disk);
save_to_disk = -1;
unlinkat(tmp_dir_fd, tmp_filename, 0);
}
}
#endif
}
return wchunk;
}
static void wsgi_end(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
PyErr_Clear();
Py_XDECREF(wsgi_req->async_placeholder);
Py_XDECREF(wsgi_req->async_environ);
fclose(wsgi_req->async_post);
#ifdef UWSGI_THREADING
if (uwsgi->has_threads && uwsgi->shared->options[UWSGI_OPTION_THREADS] == 1) {
uwsgi->_save = PyEval_SaveThread();
uwsgi->workers[uwsgi->mywid].i_have_gil = 0;
}
#endif
}
int uwsgi_request_wsgi(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
int i;
struct uwsgi_app *wi;
PyObject *zero, *wsgi_socket;
PyObject *pydictkey, *pydictvalue;
char *path_info;
PyObject *wchunk;
struct uwsgi_app *wi ;
#ifdef UWSGI_ASYNC
if (wsgi_req->async_status == UWSGI_AGAIN) {
wchunk = wsgi_response(wsgi_req->async_placeholder, wsgi_req);
if (!wchunk) {
wsgi_end(uwsgi, wsgi_req);
return UWSGI_OK ;
// get rid of timeout
if (wsgi_req->async_timeout_expired) {
PyDict_SetItemString(wsgi_req->async_environ, "x-wsgiorg.fdevent.timeout", Py_True);
wsgi_req->async_timeout_expired = 0 ;
}
Py_DECREF(wchunk);
wsgi_req->async_switches++;
return UWSGI_AGAIN ;
else {
PyDict_SetItemString(wsgi_req->async_environ, "x-wsgiorg.fdevent.timeout", Py_None);
}
return manage_python_response(uwsgi, wsgi_req);
}
#endif
@@ -116,7 +59,8 @@ int uwsgi_request_wsgi(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req
if (wsgi_req->wsgi_script_len > 0 || (wsgi_req->wsgi_callable_len > 0 && wsgi_req->wsgi_module_len > 0)) {
if ((wsgi_req->app_id = init_uwsgi_app(NULL, NULL)) == -1) {
internal_server_error(wsgi_req->poll.fd, "wsgi application not found");
wsgi_end(uwsgi, wsgi_req);
Py_DECREF(zero);
goto clear2;
}
}
}
@@ -126,7 +70,7 @@ int uwsgi_request_wsgi(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req
if (wsgi_req->app_id == -1) {
internal_server_error(wsgi_req->poll.fd, "wsgi application not found");
wsgi_end(uwsgi, wsgi_req);
goto clear2;
}
@@ -136,35 +80,40 @@ int uwsgi_request_wsgi(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req
if (uwsgi->single_interpreter == 0) {
if (!wi->interpreter) {
internal_server_error(wsgi_req->poll.fd, "wsgi application's %d interpreter not found");
wsgi_end(uwsgi, wsgi_req);
goto clear2;
}
// set the interpreter
PyThreadState_Swap(wi->interpreter);
}
wi->requests++;
if (wsgi_req->protocol_len < 5) {
fprintf(stderr, "INVALID PROTOCOL: %.*s", wsgi_req->protocol_len, wsgi_req->protocol);
internal_server_error(wsgi_req->poll.fd, "invalid HTTP protocol !!!");
wsgi_end(uwsgi, wsgi_req);
goto clear;
}
if (strncmp(wsgi_req->protocol, "HTTP/", 5)) {
fprintf(stderr, "INVALID PROTOCOL: %.*s", wsgi_req->protocol_len, wsgi_req->protocol);
internal_server_error(wsgi_req->poll.fd, "invalid HTTP protocol !!!");
wsgi_end(uwsgi, wsgi_req);
goto clear;
}
wsgi_req->async_environ = PyDict_New();
#ifdef UWSGI_ASYNC
wsgi_req->async_environ = wi->wsgi_environ[wsgi_req->async_id];
#else
wsgi_req->async_environ = wi->wsgi_environ;
#endif
Py_INCREF(wsgi_req->async_environ);
for (i = 0; i < wsgi_req->var_cnt; i += 2) {
/*fprintf(stderr,"%.*s: %.*s\n", uwsgi->hvec[i].iov_len, uwsgi->hvec[i].iov_base, uwsgi->hvec[i+1].iov_len, uwsgi->hvec[i+1].iov_base); */
pydictkey = PyString_FromStringAndSize(uwsgi->hvec[i].iov_base, uwsgi->hvec[i].iov_len);
pydictvalue = PyString_FromStringAndSize(uwsgi->hvec[i + 1].iov_base, uwsgi->hvec[i + 1].iov_len);
/*fprintf(stderr,"%.*s: %.*s\n", wsgi_req->hvec[i].iov_len, wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i+1].iov_len, wsgi_req->hvec[i+1].iov_base); */
pydictkey = PyString_FromStringAndSize(wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len);
pydictvalue = PyString_FromStringAndSize(wsgi_req->hvec[i + 1].iov_base, wsgi_req->hvec[i + 1].iov_len);
PyDict_SetItem(wsgi_req->async_environ, pydictkey, pydictvalue);
Py_DECREF(pydictkey);
Py_DECREF(pydictvalue);
@@ -203,6 +152,7 @@ int uwsgi_request_wsgi(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req
if (uwsgi->async > 1) {
PyDict_SetItemString(wsgi_req->async_environ, "x-wsgiorg.fdevent.readable", wi->wsgi_eventfd_read);
PyDict_SetItemString(wsgi_req->async_environ, "x-wsgiorg.fdevent.writable", wi->wsgi_eventfd_write);
PyDict_SetItemString(wsgi_req->async_environ, "x-wsgiorg.fdevent.timeout", Py_None);
}
#endif
@@ -243,38 +193,25 @@ int uwsgi_request_wsgi(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.url_scheme", zero);
Py_DECREF(zero);
#ifdef UNBIT
if (wsgi_req->unbit_flags & (unsigned long long) 1) {
if (uri_to_hex() <= 0) {
tmp_filename[0] = 0;
}
}
#endif
PyTuple_SetItem(wi->wsgi_args, 0, wsgi_req->async_environ);
// call
#ifdef UWSGI_PROFILER
if (uwsgi->enable_profiler == 1) {
wsgi_req->async_result = PyEval_CallObject(wi->wsgi_cprofile_run, wi->wsgi_args);
if (PyErr_Occurred()) {
PyErr_Print();
}
PyDict_SetItem(wi->pymain_dict, PyString_FromFormat("uwsgi_environ__%d", wsgi_req->app_id), wsgi_req->async_environ);
wsgi_req->async_result = python_call(wi->wsgi_cprofile_run, wi->wsgi_args);
if (wsgi_req->async_result) {
Py_DECREF(wsgi_req->async_result);
wsgi_req->async_result = PyDict_GetItemString(wi->pymain_dict, "uwsgi_out");
Py_INCREF(wsgi_req->async_result);
Py_INCREF(wsgi_req->async_result);
}
}
else {
#endif
wsgi_req->async_result = PyEval_CallObject(wi->wsgi_callable, wi->wsgi_args);
PyTuple_SetItem(wi->wsgi_args, 0, wsgi_req->async_environ);
wsgi_req->async_result = python_call(wi->wsgi_callable, wi->wsgi_args);
if (PyErr_Occurred()) {
PyErr_Print();
}
#ifdef UWSGI_PROFILER
}
#endif
@@ -286,33 +223,24 @@ int uwsgi_request_wsgi(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req
#ifdef UWSGI_SENDFILE
if (wsgi_req->sendfile_fd > -1) {
wsgi_req->response_size = uwsgi_sendfile(uwsgi, wsgi_req->sendfile_fd, wsgi_req->poll.fd);
if (wsgi_req->async_environ) {
PyDict_Clear(wsgi_req->async_environ);
}
if (wsgi_req->async_post) {
fclose(wsgi_req->async_post);
}
Py_DECREF(wsgi_req->async_result);
}
else {
#endif
wsgi_req->async_placeholder = PyObject_GetIter(wsgi_req->async_result);
if (wsgi_req->async_placeholder) {
while ( manage_python_response(uwsgi, wsgi_req) != UWSGI_OK) {
//fprintf(stderr,"WSGI CYCLE\n");
#ifdef UWSGI_ASYNC
if (uwsgi->async > 1) {
return UWSGI_AGAIN;
}
while ( (wchunk = wsgi_response(wsgi_req->async_placeholder, wsgi_req)) ) {
wsgi_req->async_switches++;
Py_DECREF(wchunk);
}
if (PyErr_Occurred()) {
PyErr_Print();
}
#ifdef UNBIT
else if (save_to_disk >= 0) {
close(save_to_disk);
save_to_disk = -1;
fprintf(stderr, "[uWSGI cacher] output of request %llu (%.*s) on pid %d written to cache file %s\n", uwsgi->workers[0].requests + 1, wsgi_req->uri_len, wsgi_req->uri, uwsgi->mypid, tmp_filename);
}
#endif
}
@@ -323,14 +251,12 @@ int uwsgi_request_wsgi(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req
}
wsgi_end(uwsgi, wsgi_req);
wi->requests++;
clear:
if (uwsgi->single_interpreter == 0) {
// restoring main interpreter
PyThreadState_Swap(uwsgi->main_thread);
}
clear2:
return UWSGI_OK;