diff --git a/plugins/http/http.c b/plugins/http/http.c index 7f771366..d1431a8b 100644 --- a/plugins/http/http.c +++ b/plugins/http/http.c @@ -142,7 +142,7 @@ struct http_session { int pass_fd; - int remains; + size_t remains; char *port; int port_len; @@ -156,6 +156,9 @@ struct http_session { char path_info[UMAX16]; uint16_t path_info_len; + size_t content_length; + size_t received_body; + struct uwsgi_subscribe_node *un; in_addr_t ip_addr; @@ -259,6 +262,10 @@ uint16_t http_add_uwsgi_header(struct http_session *h_session, struct iovec *iov h_session->hostname_len = vallen; } + if (!uwsgi_strncmp("CONTENT_LENGTH", 14, hh, keylen)) { + h_session->content_length = uwsgi_str_num(val, vallen); + } + if (uwsgi_strncmp("CONTENT_TYPE", 12, hh, keylen) && uwsgi_strncmp("CONTENT_LENGTH", 14, hh, keylen)) { keylen += 5; prefix = 1; @@ -579,6 +586,9 @@ void http_loop(int id) { uhttp_table[new_connection]->ip_addr = ((struct sockaddr_in *) &uhttp_addr)->sin_addr.s_addr; uhttp_table[new_connection]->instance_failed = 0; + uhttp_table[new_connection]->content_length = 0; + uhttp_table[new_connection]->received_body = 0; + uhttp_table[new_connection]->port = ugs->port; uhttp_table[new_connection]->port_len = ugs->port_len; @@ -768,7 +778,11 @@ void http_loop(int id) { if (uhttp_session->remains > 0) { uhttp_session->iov[uhttp_session->iov_len].iov_base = uhttp_session->ptr; + if (uhttp_session->remains > uhttp_session->content_length) { + uhttp_session->remains = uhttp_session->content_length; + } uhttp_session->iov[uhttp_session->iov_len].iov_len = uhttp_session->remains; + uhttp_session->received_body += uhttp_session->remains; uhttp_session->iov_len++; } @@ -891,6 +905,14 @@ void http_loop(int id) { } + if (uhttp_session->received_body >= uhttp_session->content_length) { + break; + } + + if (len + uhttp_session->received_body > uhttp_session->content_length) { + len = uhttp_session->content_length - uhttp_session->received_body; + } + len = send(uhttp_session->instance_fd, bbuf, len, 0); if (len <= 0) { @@ -899,6 +921,9 @@ void http_loop(int id) { close_session(uhttp_table, uhttp_session); break; } + + uhttp_session->received_body += len; + } break; diff --git a/plugins/python/python_plugin.c b/plugins/python/python_plugin.c index 2d146ecf..b3176c7a 100644 --- a/plugins/python/python_plugin.c +++ b/plugins/python/python_plugin.c @@ -192,8 +192,11 @@ void uwsgi_python_reset_random_seed() { void uwsgi_python_atexit() { + // if hijacked do not run atexit hooks + // this time we use this higher level function // as this code can be executed in a signal handler + if (!Py_IsInitialized()) { return; } @@ -1480,6 +1483,7 @@ void uwsgi_python_hijack(void) { #ifndef UWSGI_PYPY if (up.pyshell && uwsgi.mywid == 1) { + uwsgi.workers[uwsgi.mywid].hijacked = 1; // re-map stdin to stdout and stderr if we are logging to a file if (uwsgi.logfile) { if (dup2(0, 1) < 0) { diff --git a/plugins/rack/rack_plugin.c b/plugins/rack/rack_plugin.c index 0dfc442d..ea9788a4 100644 --- a/plugins/rack/rack_plugin.c +++ b/plugins/rack/rack_plugin.c @@ -61,12 +61,26 @@ VALUE rb_uwsgi_io_init(int argc, VALUE *argv, VALUE self) { VALUE rb_uwsgi_io_gets(VALUE obj, VALUE args) { + size_t i; struct wsgi_request *wsgi_req; + VALUE line; Data_Get_Struct(obj, struct wsgi_request, wsgi_req); - // return the whole body as string + // return a line of body + for(i=wsgi_req->buf_pos;ipost_cl;i++) { + if (wsgi_req->post_buffering_buf[i] == '\n') { + line = rb_str_new(wsgi_req->post_buffering_buf+wsgi_req->buf_pos, (i+1)-wsgi_req->buf_pos); + wsgi_req->buf_pos = i+1; + return line; + } + } - rb_raise(rb_eRuntimeError, "rack.input::gets is not implemented (req %p)\n", wsgi_req); + if (wsgi_req->buf_pos < wsgi_req->post_cl) { + line = rb_str_new(wsgi_req->post_buffering_buf+wsgi_req->buf_pos, wsgi_req->post_cl-wsgi_req->buf_pos); + wsgi_req->buf_pos = wsgi_req->post_cl; + return line; + } + return Qnil; } diff --git a/uwsgi.h b/uwsgi.h index e40eaac6..29e4ed59 100644 --- a/uwsgi.h +++ b/uwsgi.h @@ -1848,6 +1848,7 @@ struct uwsgi_worker { uint64_t tx; + int hijacked; int busy; int cheaped; int suspended;