mirror of
https://github.com/clearlinux/uwsgi.git
synced 2026-09-28 01:00:18 +00:00
fixed leak in python3 headers management, prepare for truly working static file serving offload
This commit is contained in:
+52
-50
@@ -965,56 +965,6 @@ ssize_t uwsgi_http_ssl_recv(struct uwsgi_corerouter *cr, struct corerouter_sessi
|
||||
|
||||
}
|
||||
|
||||
ssize_t uwsgi_http_nb_send(struct uwsgi_corerouter *cr, struct corerouter_session *cs, char *buf, size_t len) {
|
||||
struct http_session *hs = (struct http_session *) cs;
|
||||
ssize_t ret = write(cs->fd, buf, len);
|
||||
if (ret == (ssize_t) len) {
|
||||
if (cs->instance_stopped) {
|
||||
event_queue_add_fd_read(cr->queue, cs->instance_fd);
|
||||
cs->instance_stopped = 0;
|
||||
}
|
||||
if (cs->fd_state) {
|
||||
event_queue_fd_write_to_read(cr->queue, cs->fd);
|
||||
cs->fd_state = 0;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
else if (ret == 0) {
|
||||
return -1;
|
||||
}
|
||||
else if (ret < 0) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {
|
||||
if (cs->instance_fd != -1) {
|
||||
event_queue_del_fd(cr->queue, cs->instance_fd, event_queue_read());
|
||||
cs->instance_stopped = 1;
|
||||
}
|
||||
if (!cs->fd_state) {
|
||||
event_queue_fd_read_to_write(cr->queue, cs->fd);
|
||||
cs->fd_state = 1;
|
||||
}
|
||||
errno = EINPROGRESS;
|
||||
return -1;
|
||||
}
|
||||
uwsgi_error("write()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// partial write
|
||||
hs->buffer_len -= ret;
|
||||
memcpy(hs->buffer, hs->buffer + ret, hs->buffer_len);
|
||||
if (cs->instance_fd != -1) {
|
||||
event_queue_del_fd(cr->queue, cs->instance_fd, event_queue_read());
|
||||
cs->instance_stopped = 1;
|
||||
}
|
||||
if (!cs->fd_state) {
|
||||
event_queue_fd_read_to_write(cr->queue, cs->fd);
|
||||
cs->fd_state = 1;
|
||||
}
|
||||
|
||||
errno = EINPROGRESS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ssize_t uwsgi_http_ssl_send(struct uwsgi_corerouter *cr, struct corerouter_session *cs, char *buf, size_t len) {
|
||||
struct http_session *hs = (struct http_session *) cs;
|
||||
int ret = SSL_write(hs->ssl, buf, len);
|
||||
@@ -1096,6 +1046,58 @@ void uwsgi_ssl_close(struct uwsgi_corerouter *ucr, struct corerouter_session *cs
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
ssize_t uwsgi_http_nb_send(struct uwsgi_corerouter *cr, struct corerouter_session *cs, char *buf, size_t len) {
|
||||
struct http_session *hs = (struct http_session *) cs;
|
||||
ssize_t ret = write(cs->fd, buf, len);
|
||||
if (ret == (ssize_t) len) {
|
||||
if (cs->instance_stopped) {
|
||||
event_queue_add_fd_read(cr->queue, cs->instance_fd);
|
||||
cs->instance_stopped = 0;
|
||||
}
|
||||
if (cs->fd_state) {
|
||||
event_queue_fd_write_to_read(cr->queue, cs->fd);
|
||||
cs->fd_state = 0;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
else if (ret == 0) {
|
||||
return -1;
|
||||
}
|
||||
else if (ret < 0) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {
|
||||
if (cs->instance_fd != -1) {
|
||||
event_queue_del_fd(cr->queue, cs->instance_fd, event_queue_read());
|
||||
cs->instance_stopped = 1;
|
||||
}
|
||||
if (!cs->fd_state) {
|
||||
event_queue_fd_read_to_write(cr->queue, cs->fd);
|
||||
cs->fd_state = 1;
|
||||
}
|
||||
errno = EINPROGRESS;
|
||||
return -1;
|
||||
}
|
||||
uwsgi_error("write()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// partial write
|
||||
hs->buffer_len -= ret;
|
||||
memcpy(hs->buffer, hs->buffer + ret, hs->buffer_len);
|
||||
if (cs->instance_fd != -1) {
|
||||
event_queue_del_fd(cr->queue, cs->instance_fd, event_queue_read());
|
||||
cs->instance_stopped = 1;
|
||||
}
|
||||
if (!cs->fd_state) {
|
||||
event_queue_fd_read_to_write(cr->queue, cs->fd);
|
||||
cs->fd_state = 1;
|
||||
}
|
||||
|
||||
errno = EINPROGRESS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
void http_alloc_session(struct uwsgi_corerouter *ucr, struct uwsgi_gateway_socket *ugs, struct corerouter_session *cs, struct sockaddr *sa, socklen_t s_len) {
|
||||
struct http_session *hs = (struct http_session *) cs;
|
||||
hs->ptr = hs->buffer;
|
||||
|
||||
@@ -35,6 +35,13 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
|
||||
wsgi_req->headers = NULL;
|
||||
}
|
||||
|
||||
#ifdef PYTHREE
|
||||
if (wsgi_req->gc_tracker) {
|
||||
Py_DECREF((PyObject *)wsgi_req->gc_tracker);
|
||||
wsgi_req->gc_tracker = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
// this must be done before headers management
|
||||
if (PyTuple_Size(args) > 2) {
|
||||
exc_info = PyTuple_GetItem(args, 2);
|
||||
@@ -72,6 +79,10 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
|
||||
return PyErr_Format(PyExc_TypeError, "http status must be a string");
|
||||
}
|
||||
|
||||
#ifdef PYTHREE
|
||||
// this list maintains reference to encoded strings.. ugly hack, i know, but it works...
|
||||
wsgi_req->gc_tracker = (void *) PyList_New(0);
|
||||
#endif
|
||||
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_CGI_MODE] == 0) {
|
||||
base = 4;
|
||||
@@ -89,7 +100,10 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
|
||||
wsgi_req->hvec[1].iov_len = 1;
|
||||
#ifdef PYTHREE
|
||||
if (self != Py_None) {
|
||||
wsgi_req->hvec[2].iov_base = PyBytes_AsString(PyUnicode_AsASCIIString(head));
|
||||
PyObject *zero = PyUnicode_AsASCIIString(head);
|
||||
wsgi_req->hvec[2].iov_base = PyBytes_AsString(zero);
|
||||
PyList_Append((PyObject *) wsgi_req->gc_tracker, zero);
|
||||
Py_DECREF(zero);
|
||||
}
|
||||
else {
|
||||
wsgi_req->hvec[2].iov_base = PyBytes_AsString(head);
|
||||
@@ -110,7 +124,10 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
|
||||
wsgi_req->hvec[0].iov_len = 8;
|
||||
#ifdef PYTHREE
|
||||
if (self != Py_None) {
|
||||
wsgi_req->hvec[1].iov_base = PyBytes_AsString(PyUnicode_AsASCIIString(head));
|
||||
PyObject *zero = PyUnicode_AsASCIIString(head);
|
||||
wsgi_req->hvec[1].iov_base = PyBytes_AsString(zero);
|
||||
PyList_Append((PyObject *) wsgi_req->gc_tracker, zero);
|
||||
Py_DECREF(zero);
|
||||
}
|
||||
else {
|
||||
wsgi_req->hvec[1].iov_base = PyBytes_AsString(head);
|
||||
@@ -181,7 +198,10 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
|
||||
|
||||
#ifdef PYTHREE
|
||||
if (self != Py_None) {
|
||||
wsgi_req->hvec[j].iov_base = PyBytes_AsString(PyUnicode_AsASCIIString(h_key));
|
||||
PyObject *zero = PyUnicode_AsASCIIString(h_key);
|
||||
wsgi_req->hvec[j].iov_base = PyBytes_AsString(zero);
|
||||
PyList_Append((PyObject *) wsgi_req->gc_tracker, zero);
|
||||
Py_DECREF(zero);
|
||||
}
|
||||
else {
|
||||
wsgi_req->hvec[j].iov_base = PyBytes_AsString(h_key);
|
||||
@@ -195,7 +215,10 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
|
||||
wsgi_req->hvec[j + 1].iov_len = H_SEP_SIZE;
|
||||
#ifdef PYTHREE
|
||||
if (self != Py_None) {
|
||||
wsgi_req->hvec[j + 2].iov_base = PyBytes_AsString(PyUnicode_AsASCIIString(h_value));
|
||||
PyObject *zero = PyUnicode_AsASCIIString(h_value);
|
||||
wsgi_req->hvec[j + 2].iov_base = PyBytes_AsString(zero);
|
||||
PyList_Append((PyObject *) wsgi_req->gc_tracker, zero);
|
||||
Py_DECREF(zero);
|
||||
}
|
||||
else {
|
||||
wsgi_req->hvec[j + 2].iov_base = PyBytes_AsString(h_value);
|
||||
@@ -288,6 +311,13 @@ int uwsgi_python_do_send_headers(struct wsgi_request *wsgi_req) {
|
||||
wsgi_req->headers = NULL;
|
||||
}
|
||||
|
||||
#ifdef PYTHREE
|
||||
if (wsgi_req->gc_tracker) {
|
||||
Py_DECREF((PyObject *)wsgi_req->gc_tracker);
|
||||
wsgi_req->gc_tracker = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (wsgi_req->write_errors > uwsgi.write_errors_tolerance && !uwsgi.disable_write_exception) {
|
||||
uwsgi_py_write_set_exception(wsgi_req);
|
||||
return -1;
|
||||
|
||||
Reference in New Issue
Block a user