Python: releasing GIL while waiting for a request.
It unblocks other threads that can be forked by the application
to work in background.
This closes issue on GitHub.
@@ -151,6 +151,7 @@ static wchar_t *nxt_py_home;
static char *nxt_py_home;
#endif
+static PyThreadState *nxt_python_thread_state;
static nxt_python_run_ctx_t *nxt_python_run_ctx;
@@ -340,10 +341,14 @@ nxt_python_init(nxt_task_t *task, nxt_common_app_conf_t *conf)
goto fail;
}
+ nxt_python_thread_state = PyEval_SaveThread();
+
rc = nxt_unit_run(unit_ctx);
nxt_unit_done(unit_ctx);
+ PyEval_RestoreThread(nxt_python_thread_state);
+
nxt_python_atexit();
exit(rc);
@@ -368,19 +373,20 @@ nxt_python_request_handler(nxt_unit_request_info_t *req)
PyObject *result, *iterator, *item, *args, *environ;
nxt_python_run_ctx_t run_ctx = {-1, 0, NULL, req};
+ PyEval_RestoreThread(nxt_python_thread_state);
+
environ = nxt_python_get_environ(&run_ctx);
if (nxt_slow_path(environ == NULL)) {
- nxt_unit_request_done(req, NXT_UNIT_ERROR);
-
- return;
+ rc = NXT_UNIT_ERROR;
+ goto done;
}
args = PyTuple_New(2);
if (nxt_slow_path(args == NULL)) {
nxt_unit_req_error(req, "Python failed to create arguments tuple");
- nxt_unit_request_done(req, NXT_UNIT_ERROR);
- return;
+ rc = NXT_UNIT_ERROR;
+ goto done;
}
PyTuple_SET_ITEM(args, 0, environ);
@@ -398,10 +404,8 @@ nxt_python_request_handler(nxt_unit_request_info_t *req)
nxt_unit_req_error(req, "Python failed to call the application");
PyErr_Print();
- nxt_unit_request_done(req, NXT_UNIT_ERROR);
- nxt_python_run_ctx = NULL;
-
- return;
+ rc = NXT_UNIT_ERROR;
+ goto done;
}
item = NULL;
@@ -455,13 +459,11 @@ nxt_python_request_handler(nxt_unit_request_info_t *req)
PyErr_Print();
}
- nxt_unit_request_done(req, NXT_UNIT_OK);
-
Py_DECREF(result);
- nxt_python_run_ctx = NULL;
+ rc = NXT_UNIT_OK;
- return;
+ goto done;
fail:
@@ -478,9 +480,15 @@ nxt_python_request_handler(nxt_unit_request_info_t *req)
}
Py_DECREF(result);
- nxt_python_run_ctx = NULL;
- nxt_unit_request_done(req, NXT_UNIT_ERROR);
+ rc = NXT_UNIT_ERROR;
+
+done:
+
+ nxt_python_thread_state = PyEval_SaveThread();
+
+ nxt_python_run_ctx = NULL;
+ nxt_unit_request_done(req, rc);
}
