From 9852b2fa6295bff3bd033bd6a24766bdddb41b3d Mon Sep 17 00:00:00 2001 From: "roberto@sirius" Date: Sun, 21 Mar 2010 08:53:36 +0100 Subject: [PATCH] async sleep implementation, kqueue re-broken, profiler leaks memory --- async.c | 90 ++++++++++++++- protocol.c | 34 +++--- pyutils.c | 120 ++++++++++++++++++++ simple_app.py | 2 +- tests/cpubound_async.py | 5 +- tests/sleeping_async.py | 9 ++ staticfile.py => tests/staticfile.py | 3 +- uwsgi.c | 160 +++++++++++++++++---------- uwsgi.h | 26 ++++- uwsgi_handlers.c | 35 ++---- uwsgi_pymodule.c | 24 ++++ uwsgiconfig.py | 2 +- wsgi_handlers.c | 160 +++++++-------------------- 13 files changed, 442 insertions(+), 228 deletions(-) create mode 100644 pyutils.c create mode 100644 tests/sleeping_async.py rename staticfile.py => tests/staticfile.py (74%) diff --git a/async.c b/async.c index 4c25924c..dd902564 100644 --- a/async.c +++ b/async.c @@ -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;iasync;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;iasync;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;iasync;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; } diff --git a/protocol.c b/protocol.c index 4292b552..f8f0821f 100644 --- a/protocol.c +++ b/protocol.c @@ -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++; } diff --git a/pyutils.c b/pyutils.c new file mode 100644 index 00000000..3201389d --- /dev/null +++ b/pyutils.c @@ -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; +} diff --git a/simple_app.py b/simple_app.py index e84310fd..1c4ce07f 100644 --- a/simple_app.py +++ b/simple_app.py @@ -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" diff --git a/tests/cpubound_async.py b/tests/cpubound_async.py index 901392d6..6da36316 100644 --- a/tests/cpubound_async.py +++ b/tests/cpubound_async.py @@ -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 "

%s

" % i + for i in range(1,100000): + yield "

%s at %s

" % (i, str(time.time())) diff --git a/tests/sleeping_async.py b/tests/sleeping_async.py new file mode 100644 index 00000000..9ba10bf5 --- /dev/null +++ b/tests/sleeping_async.py @@ -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 "

Hello World after %d seconds

" % sleepvalue diff --git a/staticfile.py b/tests/staticfile.py similarity index 74% rename from staticfile.py rename to tests/staticfile.py index f8ab2f6f..ab1230c6 100644 --- a/staticfile.py +++ b/tests/staticfile.py @@ -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) diff --git a/uwsgi.c b/uwsgi.c index 09a02399..bceb0ba5 100644 --- a/uwsgi.c +++ b/uwsgi.c @@ -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; isendfile_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;iwsgi_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); diff --git a/uwsgi.h b/uwsgi.h index c3c2404a..c903f41e 100644 --- a/uwsgi.h +++ b/uwsgi.h @@ -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 *); diff --git a/uwsgi_handlers.c b/uwsgi_handlers.c index 0f862edd..e893b071 100644 --- a/uwsgi_handlers.c +++ b/uwsgi_handlers.c @@ -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 */ diff --git a/uwsgi_pymodule.c b/uwsgi_pymodule.c index c24a129a..f5e7e1d8 100644 --- a/uwsgi_pymodule.c +++ b/uwsgi_pymodule.c @@ -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}, diff --git a/uwsgiconfig.py b/uwsgiconfig.py index 74518dd3..7c7e68c6 100644 --- a/uwsgiconfig.py +++ b/uwsgiconfig.py @@ -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'] diff --git a/wsgi_handlers.c b/wsgi_handlers.c index d9c83120..4b9ecd4e 100644 --- a/wsgi_handlers.c +++ b/wsgi_handlers.c @@ -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;