summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorMax Romanov <max.romanov@nginx.com>2022-02-08 12:04:41 +0300
committerMax Romanov <max.romanov@nginx.com>2022-02-08 12:04:41 +0300
commit2b5941df74806d344c59ec0ca126b81cc7bbffe1 (patch)
tree653202ded2ce98760c5d4bc81b60ae11fd889db5
parente53ce40c5854d95722cdfc198626fcd5aecbe563 (diff)
downloadunit-2b5941df74806d344c59ec0ca126b81cc7bbffe1.tar.gz
unit-2b5941df74806d344c59ec0ca126b81cc7bbffe1.tar.bz2
Python: fixing incorrect function object dereference.
The __call__ method can be native and not be a PyFunction type. A type check is thus required before accessing op_code and other fields. Reproduced on Ubuntu 21.04, Python 3.9.4 and Falcon framework: here, the App.__call__ method is compiled with Cython, so accessing op_code->co_flags is invalid; accidentally, the COROUTINE bit is set which forces the Python module into the ASGI mode. The workaround is explicit protocol specification. Note: it is impossible to specify the legacy mode for ASGI.
-rw-r--r--docs/changes.xml7
-rw-r--r--src/python/nxt_python_asgi.c18
2 files changed, 19 insertions, 6 deletions
diff --git a/docs/changes.xml b/docs/changes.xml
index 64a35da8..a6b1178d 100644
--- a/docs/changes.xml
+++ b/docs/changes.xml
@@ -43,6 +43,13 @@ some Spring Boot applications failed to start, notably with Grails.
</para>
</change>
+<change type="bugfix">
+<para>
+incorrect Python protocol auto detection (ASGI or WSGI) for native callable
+object, notably with Falcon.
+</para>
+</change>
+
</changes>
diff --git a/src/python/nxt_python_asgi.c b/src/python/nxt_python_asgi.c
index 354e3a81..2d3efc7d 100644
--- a/src/python/nxt_python_asgi.c
+++ b/src/python/nxt_python_asgi.c
@@ -117,15 +117,20 @@ nxt_python_asgi_get_func(PyObject *obj)
if (PyMethod_Check(call)) {
obj = PyMethod_GET_FUNCTION(call);
- Py_INCREF(obj);
- Py_DECREF(call);
+ if (PyFunction_Check(obj)) {
+ Py_INCREF(obj);
- return obj;
+ } else {
+ obj = NULL;
+ }
+
+ } else {
+ obj = NULL;
}
Py_DECREF(call);
- return NULL;
+ return obj;
}
@@ -161,8 +166,9 @@ nxt_python_asgi_init(nxt_unit_init_t *init, nxt_python_proto_t *proto)
for (i = 0; i < nxt_py_targets->count; i++) {
func = nxt_python_asgi_get_func(nxt_py_targets->target[i].application);
if (nxt_slow_path(func == NULL)) {
- nxt_unit_alert(NULL, "Python cannot find function for callable");
- return NXT_UNIT_ERROR;
+ nxt_unit_debug(NULL, "asgi: cannot find function for callable, "
+ "unable to check for legacy mode (#%d)", i);
+ continue;
}
code = (PyCodeObject *) PyFunction_GET_CODE(func);