From 75c2c23bb6cd95a9e08d89f74e6457321d266ed2 Mon Sep 17 00:00:00 2001 From: Valentin Bartenev Date: Thu, 14 Nov 2019 17:48:48 +0300 Subject: [PATCH] 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. --- src/nxt_python_wsgi.c | 29 +++++++++++++++++++---------- 1 file 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: