From 37e153d5de9edfb0eae270a398a3b353a8663bd9 Mon Sep 17 00:00:00 2001 From: Roberto De Ioris Date: Sun, 20 Jan 2013 10:32:02 +0100 Subject: [PATCH] need to find a way to better manage write errors... --- core/utils.c | 8 ++ core/writer.c | 1 - plugins/gevent/gevent.c | 1 - plugins/python/pump_subhandler.c | 93 ++++----------------- plugins/python/python_plugin.c | 7 -- plugins/python/uwsgi_pymodule.c | 20 +---- plugins/python/uwsgi_python.h | 1 - plugins/python/web3_subhandler.c | 5 -- plugins/python/wsgi_handlers.c | 7 +- plugins/python/wsgi_subhandler.c | 5 -- plugins/router_basicauth/router_basicauth.c | 2 + plugins/router_cache/router_cache.c | 2 +- plugins/router_redirect/router_redirect.c | 4 +- plugins/rpc/rpc_plugin.c | 6 +- 14 files changed, 35 insertions(+), 127 deletions(-) diff --git a/core/utils.c b/core/utils.c index df4eca9e..e7de617b 100644 --- a/core/utils.c +++ b/core/utils.c @@ -659,6 +659,14 @@ void uwsgi_close_request(struct wsgi_request *wsgi_req) { int tmp_id; uint64_t tmp_rt, rss = 0, vsz = 0; + // check if headers should be sent + if (wsgi_req->headers) { + if (!wsgi_req->headers_sent && !wsgi_req->headers_size && !wsgi_req->response_size) { + uwsgi_response_write_headers_do(wsgi_req); + } + uwsgi_buffer_destroy(wsgi_req->headers); + } + wsgi_req->end_of_request = uwsgi_micros(); tmp_rt = wsgi_req->end_of_request - wsgi_req->start_of_request; diff --git a/core/writer.c b/core/writer.c index 10ac4007..35b52f05 100644 --- a/core/writer.c +++ b/core/writer.c @@ -127,7 +127,6 @@ sendfile: } for(;;) { - uwsgi_log("XXXX %d %d\n", pos, len); int ret = wsgi_req->socket->proto_sendfile(wsgi_req, fd, pos, len); if (ret < 0) { if (!uwsgi.ignore_write_errors) { diff --git a/plugins/gevent/gevent.c b/plugins/gevent/gevent.c index ae7d0f5a..a7dc4a0c 100644 --- a/plugins/gevent/gevent.c +++ b/plugins/gevent/gevent.c @@ -964,7 +964,6 @@ void gevent_loop() { } uwsgi.current_wsgi_req = uwsgi_gevent_current_wsgi_req; - up.hook_write_string = uwsgi_gevent_nb_write; up.hook_wsgi_input_read = uwsgi_gevent_hook_input_read; up.hook_wsgi_input_readline = uwsgi_gevent_hook_input_readline; diff --git a/plugins/python/pump_subhandler.c b/plugins/python/pump_subhandler.c index 36c2cf87..94b50670 100644 --- a/plugins/python/pump_subhandler.c +++ b/plugins/python/pump_subhandler.c @@ -179,10 +179,8 @@ void *uwsgi_request_subhandler_pump(struct wsgi_request *wsgi_req, struct uwsgi_ int uwsgi_response_subhandler_pump(struct wsgi_request *wsgi_req) { PyObject *pychunk; - ssize_t wsize; int i; - struct http_status_codes *http_sc; char sc[4]; // ok its a yield @@ -220,39 +218,7 @@ int uwsgi_response_subhandler_pump(struct wsgi_request *wsgi_req) { goto clear; } - int found = 0; - for (http_sc = hsc; http_sc->message != NULL; http_sc++) { - if (http_sc->key[0] == sc[0] && http_sc->key[1] == sc[1] && http_sc->key[2] == sc[2]) { - wsgi_req->hvec[4].iov_base = (char *) http_sc->message; - wsgi_req->hvec[4].iov_len = http_sc->message_size; - found = 1; - break; - } - } - - if (!found) { - uwsgi_log("invalid Pump response (status code).\n"); - goto clear; - } - - wsgi_req->hvec[0].iov_base = wsgi_req->protocol; - wsgi_req->hvec[0].iov_len = wsgi_req->protocol_len; - wsgi_req->hvec[1].iov_base = " "; - wsgi_req->hvec[1].iov_len = 1; - wsgi_req->hvec[2].iov_base = sc; - wsgi_req->hvec[2].iov_len = 3; - wsgi_req->hvec[3].iov_base = " "; - wsgi_req->hvec[3].iov_len = 1; - wsgi_req->hvec[5].iov_base = "\r\n"; - wsgi_req->hvec[5].iov_len = 2; - - UWSGI_RELEASE_GIL - wsize = wsgi_req->socket->proto_writev_header(wsgi_req, wsgi_req->hvec, 6); - UWSGI_GET_GIL - if (wsize < 0) { - uwsgi_error("writev()"); - } - wsgi_req->headers_size += wsize; + uwsgi_response_prepare_headers(wsgi_req, sc, 3); PyObject *hhkey, *hhvalue; #ifdef UWSGI_PYTHON_OLD @@ -263,53 +229,29 @@ int uwsgi_response_subhandler_pump(struct wsgi_request *wsgi_req) { while (PyDict_Next(headers, &hhpos, &hhkey, &hhvalue)) { if (!PyString_Check(hhkey)) continue; - wsgi_req->hvec[0].iov_base = PyString_AsString(hhkey); - wsgi_req->hvec[0].iov_len = PyString_Size(hhkey); - ((char*)wsgi_req->hvec[0].iov_base)[0] = toupper((int) ((char*)wsgi_req->hvec[0].iov_base)[0]); + char *k = PyString_AsString(hhkey); + size_t kl = PyString_Size(hhkey); + k[0] = toupper((int) k[0]); - wsgi_req->hvec[1].iov_base = ": "; - wsgi_req->hvec[1].iov_len = 2; - - wsgi_req->hvec[3].iov_base = "\r\n"; - wsgi_req->hvec[3].iov_len = 2; if (PyList_Check(hhvalue)) { for(i=0;ihvec[2].iov_base = PyString_AsString(item); - wsgi_req->hvec[2].iov_len = PyString_Size(item); - UWSGI_RELEASE_GIL - wsize = wsgi_req->socket->proto_writev_header(wsgi_req, wsgi_req->hvec, 4); - UWSGI_GET_GIL - if (wsize < 0) { - uwsgi_error("writev()"); - } - wsgi_req->headers_size += wsize; + uwsgi_response_add_header(wsgi_req, k, kl, PyString_AsString(item), PyString_Size(item)); } } } else if (PyString_Check(hhvalue)) { - wsgi_req->hvec[2].iov_base = PyString_AsString(hhvalue); - wsgi_req->hvec[2].iov_len = PyString_Size(hhvalue); - UWSGI_RELEASE_GIL - wsize = wsgi_req->socket->proto_writev_header(wsgi_req, wsgi_req->hvec, 4); - UWSGI_GET_GIL - if (wsize < 0) { - uwsgi_error("writev()"); - } - wsgi_req->headers_size += wsize; + uwsgi_response_add_header(wsgi_req, k, kl, PyString_AsString(hhvalue), PyString_Size(hhvalue)); } } - wsgi_req->socket->proto_write(wsgi_req, "\r\n", 2); Py_INCREF((PyObject *)wsgi_req->async_placeholder); if (PyString_Check((PyObject *)wsgi_req->async_placeholder)) { - if ((wsize = wsgi_req->socket->proto_write(wsgi_req, PyString_AsString(wsgi_req->async_placeholder), PyString_Size(wsgi_req->async_placeholder))) < 0) { - uwsgi_error("write()"); - goto clear; - } - wsgi_req->response_size += wsize; + UWSGI_RELEASE_GIL + uwsgi_response_write_body_do(wsgi_req, PyString_AsString(wsgi_req->async_placeholder), PyString_Size(wsgi_req->async_placeholder)); + UWSGI_GET_GIL goto clear; } #ifdef PYTHREE @@ -318,11 +260,9 @@ int uwsgi_response_subhandler_pump(struct wsgi_request *wsgi_req) { else if (PyFile_Check((PyObject *)wsgi_req->async_placeholder)) { wsgi_req->sendfile_fd = fileno(PyFile_AsFile((PyObject *)wsgi_req->async_placeholder)); #endif - wsize = uwsgi_sendfile(wsgi_req); - if (wsize < 0) { - goto clear; - } - wsgi_req->response_size += wsize; + UWSGI_RELEASE_GIL + uwsgi_response_sendfile_do(wsgi_req, wsgi_req->sendfile_fd, 0, 0); + UWSGI_GET_GIL goto clear; } @@ -358,12 +298,9 @@ int uwsgi_response_subhandler_pump(struct wsgi_request *wsgi_req) { if (PyString_Check(pychunk)) { - if ((wsize = wsgi_req->socket->proto_write(wsgi_req, PyString_AsString(pychunk), PyString_Size(pychunk))) < 0) { - uwsgi_error("write()"); - Py_DECREF(pychunk); - goto clear; - } - wsgi_req->response_size += wsize; + UWSGI_RELEASE_GIL + uwsgi_response_write_body_do(wsgi_req, PyString_AsString(pychunk), PyString_Size(pychunk)); + UWSGI_GET_GIL } diff --git a/plugins/python/python_plugin.c b/plugins/python/python_plugin.c index 68df9d9b..623fb6a7 100644 --- a/plugins/python/python_plugin.c +++ b/plugins/python/python_plugin.c @@ -9,12 +9,6 @@ extern struct http_status_codes hsc[]; extern PyTypeObject uwsgi_InputType; -void python_simple_hook_write_string(struct wsgi_request *wsgi_req, PyObject *str) { - UWSGI_RELEASE_GIL - wsgi_req->response_size += wsgi_req->socket->proto_write(wsgi_req, PyString_AsString(str), PyString_Size(str)); - UWSGI_GET_GIL -} - void uwsgi_opt_pythonpath(char *opt, char *value, void *foobar) { int i; @@ -257,7 +251,6 @@ pep405: up.wsgi_spitout = PyCFunction_New(uwsgi_spit_method, NULL); up.wsgi_writeout = PyCFunction_New(uwsgi_write_method, NULL); - up.hook_write_string = python_simple_hook_write_string; up.hook_wsgi_input_read = uwsgi_python_hook_simple_input_read; up.hook_wsgi_input_readline = uwsgi_python_hook_simple_input_readline; diff --git a/plugins/python/uwsgi_pymodule.c b/plugins/python/uwsgi_pymodule.c index 25eb2ef7..220246e4 100644 --- a/plugins/python/uwsgi_pymodule.c +++ b/plugins/python/uwsgi_pymodule.c @@ -809,7 +809,7 @@ PyObject *py_uwsgi_offload_transfer(PyObject * self, PyObject * args) { } if (!wsgi_req->headers_sent) { - if (uwsgi_python_do_send_headers(wsgi_req)) { + if (uwsgi_response_write_headers_do(wsgi_req)) { return PyErr_Format(PyExc_ValueError, "unable to send headers before offload transfer"); } } @@ -884,21 +884,9 @@ PyObject *py_uwsgi_advanced_sendfile(PyObject * self, PyObject * args) { wsgi_req->sendfile_fd_chunk = chunk; wsgi_req->sendfile_fd_pos = pos; - // do sendfile - if (uwsgi.async > 1) { - ssize_t sf_len = uwsgi_sendfile(wsgi_req); - if (sf_len > 0) { - wsgi_req->response_size += sf_len; - while((size_t)wsgi_req->sendfile_fd_pos < wsgi_req->sendfile_fd_size) { - sf_len = uwsgi_sendfile(wsgi_req); - if (sf_len <= 0) break; - wsgi_req->response_size += sf_len; - } - } - } - else { - wsgi_req->response_size += uwsgi_sendfile(wsgi_req); - } + UWSGI_RELEASE_GIL + uwsgi_response_sendfile_do(wsgi_req, wsgi_req->sendfile_fd, wsgi_req->sendfile_fd_pos, wsgi_req->sendfile_fd_size); + UWSGI_GET_GIL // revert to old values wsgi_req->sendfile_fd = tmp_fd; diff --git a/plugins/python/uwsgi_python.h b/plugins/python/uwsgi_python.h index 993b30ae..a7838133 100644 --- a/plugins/python/uwsgi_python.h +++ b/plugins/python/uwsgi_python.h @@ -186,7 +186,6 @@ struct uwsgi_python { char *pyrun; int start_response_nodelay; - void (*hook_write_string)(struct wsgi_request *, PyObject *); ssize_t (*hook_wsgi_input_read)(struct wsgi_request *, char *, size_t, size_t *); ssize_t (*hook_wsgi_input_readline)(struct wsgi_request *, char *, size_t); diff --git a/plugins/python/web3_subhandler.c b/plugins/python/web3_subhandler.c index 705a249a..5b2a4167 100644 --- a/plugins/python/web3_subhandler.c +++ b/plugins/python/web3_subhandler.c @@ -164,11 +164,6 @@ int uwsgi_response_subhandler_web3(struct wsgi_request *wsgi_req) { goto clear; } - // send the headers if not already sent - if (!wsgi_req->headers_sent && wsgi_req->headers_hvec > 0) { - uwsgi_python_do_send_headers(wsgi_req); - } - Py_DECREF(spit_args); if (PyString_Check((PyObject *)wsgi_req->async_placeholder)) { diff --git a/plugins/python/wsgi_handlers.c b/plugins/python/wsgi_handlers.c index d958daac..9a880bbb 100644 --- a/plugins/python/wsgi_handlers.c +++ b/plugins/python/wsgi_handlers.c @@ -296,13 +296,8 @@ PyObject *py_uwsgi_write(PyObject * self, PyObject * args) { if (PyString_Check(data)) { content = PyString_AsString(data); content_len = PyString_Size(data); - if (content_len > 0 && !wsgi_req->headers_sent) { - if (uwsgi_python_do_send_headers(wsgi_req)) { - return NULL; - } - } UWSGI_RELEASE_GIL - wsgi_req->response_size = wsgi_req->socket->proto_write(wsgi_req, content, content_len); + uwsgi_response_write_body_do(wsgi_req, content, content_len); UWSGI_GET_GIL // this is a special case for the write callable // no need to honout write-errors-exception-only diff --git a/plugins/python/wsgi_subhandler.c b/plugins/python/wsgi_subhandler.c index c7e8ca29..3fc1ae15 100644 --- a/plugins/python/wsgi_subhandler.c +++ b/plugins/python/wsgi_subhandler.c @@ -242,11 +242,6 @@ clear: Py_DECREF((PyObject *)wsgi_req->async_sendfile); } - // send the headers if not already sent - if (!wsgi_req->headers_sent && wsgi_req->headers_hvec > 0) { - uwsgi_python_do_send_headers(wsgi_req); - } - if (wsgi_req->async_placeholder) { // CALL close() ALWAYS if we are working with an iterator !!! if (PyObject_HasAttrString((PyObject *)wsgi_req->async_result, "close")) { diff --git a/plugins/router_basicauth/router_basicauth.c b/plugins/router_basicauth/router_basicauth.c index c6a47a87..77d607fa 100644 --- a/plugins/router_basicauth/router_basicauth.c +++ b/plugins/router_basicauth/router_basicauth.c @@ -112,6 +112,7 @@ int uwsgi_routing_func_basicauth(struct wsgi_request *wsgi_req, struct uwsgi_rou } forbidden: +/* iov[1].iov_base = " 401 Authorization Required\r\nWWW-Authenticate: Basic realm=\""; iov[1].iov_len = 60 ; @@ -124,6 +125,7 @@ forbidden: wsgi_req->headers_size = wsgi_req->socket->proto_writev_header(wsgi_req, iov, 4); wsgi_req->response_size = wsgi_req->socket->proto_write(wsgi_req,"Unauthorized", 12); +*/ wsgi_req->status = 401; diff --git a/plugins/router_cache/router_cache.c b/plugins/router_cache/router_cache.c index 60c958ad..7acf50a0 100644 --- a/plugins/router_cache/router_cache.c +++ b/plugins/router_cache/router_cache.c @@ -72,7 +72,7 @@ static int uwsgi_routing_func_cache(struct wsgi_request *wsgi_req, struct uwsgi_ if (uwsgi_buffer_append(ub, "\r\nContent-Length: ", 18 )) goto error; if (uwsgi_buffer_num64(ub, valsize)) goto error; if (uwsgi_buffer_append(ub, "\r\n\r\n", 4 )) goto error; - wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, ub->buf, ub->pos); + //wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, ub->buf, ub->pos); uwsgi_buffer_destroy(ub); wsgi_req->header_cnt = 3; } diff --git a/plugins/router_redirect/router_redirect.c b/plugins/router_redirect/router_redirect.c index 2c5ae2a6..81a5aaee 100644 --- a/plugins/router_redirect/router_redirect.c +++ b/plugins/router_redirect/router_redirect.c @@ -8,7 +8,7 @@ int uwsgi_routing_func_redirect(struct wsgi_request *wsgi_req, struct uwsgi_rout char *url = NULL; - if (uwsgi_response_headers_prepare(wsgi_req, "302 Found", 9)) goto end + if (uwsgi_response_prepare_headers(wsgi_req, "302 Found", 9)) goto end; char **subject = (char **) (((char *)(wsgi_req))+ur->subject); uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len); @@ -17,7 +17,7 @@ int uwsgi_routing_func_redirect(struct wsgi_request *wsgi_req, struct uwsgi_rout if (uwsgi_response_add_header(wsgi_req, "Location", 8, url, strlen(url))) goto end; // no need to check the ret value - uwsgi_response_body_write_do(wsgi_req, "Moved", 5); + uwsgi_response_write_body_do(wsgi_req, "Moved", 5); end: if (url) free(url); diff --git a/plugins/rpc/rpc_plugin.c b/plugins/rpc/rpc_plugin.c index 505bd6ea..6eddfed4 100644 --- a/plugins/rpc/rpc_plugin.c +++ b/plugins/rpc/rpc_plugin.c @@ -37,11 +37,9 @@ int uwsgi_rpc_request(struct wsgi_request *wsgi_req) { wsgi_req->uh.pktsize = uwsgi_rpc(argv[0], argc-1, argv+1, argvs+1, wsgi_req->buffer); if (wsgi_req->uh.modifier2 == 0) { - wsgi_req->headers_size = wsgi_req->socket->proto_write_header(wsgi_req, (char *)&wsgi_req->uh, 4); + uwsgi_response_write_body_do(wsgi_req, (char *)&wsgi_req->uh, 4); } - - wsgi_req->response_size = wsgi_req->socket->proto_write(wsgi_req, wsgi_req->buffer, wsgi_req->uh.pktsize); - wsgi_req->status = 0; + uwsgi_response_write_body_do(wsgi_req, wsgi_req->buffer, wsgi_req->uh.pktsize); return 0; }