diff options
author | Valentin Bartenev <vbart@nginx.com> | 2019-11-14 17:48:48 +0300 |
---|---|---|
committer | Valentin Bartenev <vbart@nginx.com> | 2019-11-14 17:48:48 +0300 |
commit | 75c2c23bb6cd95a9e08d89f74e6457321d266ed2 (patch) | |
tree | 0212dbdbb5ddce3497906aaf70f613595ce7ca5e | |
parent | c667bb446d866f1a1a786fa9a3b3ecd06d163cfb (diff) | |
download | unit-75c2c23bb6cd95a9e08d89f74e6457321d266ed2.tar.gz unit-75c2c23bb6cd95a9e08d89f74e6457321d266ed2.tar.bz2 |
Python: fixed an object leak when response close() is called.
On success, PyObject_CallMethod() returns a new reference to
the result of the call, which previously got lost.
Also, error logging on failure was added.
The issue was introduced by b0148ec28c4d.
-rw-r--r-- | src/nxt_python_wsgi.c | 29 |
1 files changed, 19 insertions, 10 deletions
diff --git a/src/nxt_python_wsgi.c b/src/nxt_python_wsgi.c index 16298c05..54892580 100644 --- a/src/nxt_python_wsgi.c +++ b/src/nxt_python_wsgi.c @@ -370,7 +370,7 @@ static void nxt_python_request_handler(nxt_unit_request_info_t *req) { int rc; - PyObject *result, *iterator, *item, *args, *environ; + PyObject *environ, *args, *response, *iterator, *item, *result; nxt_python_run_ctx_t run_ctx = {-1, 0, NULL, req}; PyEval_RestoreThread(nxt_python_thread_state); @@ -398,11 +398,11 @@ nxt_python_request_handler(nxt_unit_request_info_t *req) nxt_python_run_ctx = &run_ctx; - result = PyObject_CallObject(nxt_py_application, args); + response = PyObject_CallObject(nxt_py_application, args); Py_DECREF(args); - if (nxt_slow_path(result == NULL)) { + if (nxt_slow_path(response == NULL)) { nxt_unit_req_error(req, "Python failed to call the application"); PyErr_Print(); @@ -410,12 +410,12 @@ nxt_python_request_handler(nxt_unit_request_info_t *req) goto done; } - /* Shortcut: avoid iterate over result string symbols. */ - if (PyBytes_Check(result)) { - rc = nxt_python_write(&run_ctx, result); + /* Shortcut: avoid iterate over response string symbols. */ + if (PyBytes_Check(response)) { + rc = nxt_python_write(&run_ctx, response); } else { - iterator = PyObject_GetIter(result); + iterator = PyObject_GetIter(response); if (nxt_fast_path(iterator != NULL)) { rc = NXT_UNIT_OK; @@ -461,12 +461,21 @@ nxt_python_request_handler(nxt_unit_request_info_t *req) rc = NXT_UNIT_ERROR; } - if (PyObject_HasAttrString(result, "close")) { - PyObject_CallMethod(result, (char *) "close", NULL); + if (PyObject_HasAttrString(response, "close")) { + result = PyObject_CallMethod(response, (char *) "close", NULL); + + if (nxt_fast_path(result != NULL)) { + Py_DECREF(result); + + } else { + nxt_unit_req_error(req, "Python failed to call the close() " + "method of the application response"); + PyErr_Print(); + } } } - Py_DECREF(result); + Py_DECREF(response); done: |