commit 9bcccb9483284deb96575dcbd94ead5d4571a8c6
parent dbb99a56d1fc522473517af0da4e16dc5b9ac0d0
Author: Joris Vink <joris@coders.se>
Date: Mon, 16 Sep 2019 20:11:42 +0200
Add coroutine debugging.
If built with PYTHON_CORO_DEBUG in CFLAGS Kore will spew out coroutine
traces while running. These traces include the filename, function and line
number where the coroutines are waking up, running and suspended.
Diffstat:
2 files changed, 52 insertions(+), 4 deletions(-)
diff --git a/include/kore/python_api.h b/include/kore/python_api.h
@@ -22,6 +22,7 @@
#undef _XOPEN_SOURCE
#include <Python.h>
+#include <frameobject.h>
void kore_python_init(void);
void kore_python_preinit(void);
diff --git a/src/python.c b/src/python.c
@@ -40,6 +40,10 @@
#include "python_api.h"
#include "python_methods.h"
+#if defined(PYTHON_CORO_DEBUG)
+#include <frameobject.h>
+#endif
+
struct reqcall {
PyObject *f;
TAILQ_ENTRY(reqcall) list;
@@ -59,9 +63,14 @@ static PyObject *pyhttp_request_alloc(const struct http_request *);
static struct python_coro *python_coro_create(PyObject *,
struct http_request *);
-static int python_coro_run(struct python_coro *);
-static void python_coro_wakeup(struct python_coro *);
-static void python_coro_suspend(struct python_coro *);
+
+static int python_coro_run(struct python_coro *);
+static void python_coro_wakeup(struct python_coro *);
+static void python_coro_suspend(struct python_coro *);
+
+#if defined(PYTHON_CORO_DEBUG)
+static void python_coro_trace(const char *, struct python_coro *);
+#endif
static void pysocket_evt_handle(void *, int);
static void pysocket_op_timeout(void *, u_int64_t);
@@ -571,8 +580,11 @@ python_coro_run(struct python_coro *coro)
coro_running = coro;
for (;;) {
- PyErr_Clear();
+#if defined(PYTHON_CORO_DEBUG)
+ python_coro_trace("running", coro);
+#endif
+ PyErr_Clear();
item = _PyGen_Send((PyGenObject *)coro->obj, NULL);
if (item == NULL) {
if (coro->gatherop == NULL && PyErr_Occurred() &&
@@ -614,6 +626,10 @@ python_coro_wakeup(struct python_coro *coro)
coro->state = CORO_STATE_RUNNABLE;
TAILQ_REMOVE(&coro_suspended, coro, list);
TAILQ_INSERT_TAIL(&coro_runnable, coro, list);
+
+#if defined(PYTHON_CORO_DEBUG)
+ python_coro_trace("wokeup", coro);
+#endif
}
static void
@@ -625,8 +641,39 @@ python_coro_suspend(struct python_coro *coro)
coro->state = CORO_STATE_SUSPENDED;
TAILQ_REMOVE(&coro_runnable, coro, list);
TAILQ_INSERT_TAIL(&coro_suspended, coro, list);
+
+#if defined(PYTHON_CORO_DEBUG)
+ python_coro_trace("suspended", coro);
+#endif
}
+#if defined(PYTHON_CORO_DEBUG)
+static void
+python_coro_trace(const char *label, struct python_coro *coro)
+{
+ int line;
+ PyGenObject *gen;
+ PyCodeObject *code;
+ const char *func, *fname, *file;
+
+ gen = (PyGenObject *)coro->obj;
+ code = gen->gi_frame->f_code;
+
+ func = PyUnicode_AsUTF8AndSize(code->co_name, NULL);
+ file = PyUnicode_AsUTF8AndSize(code->co_filename, NULL);
+
+ line = PyFrame_GetLineNumber(gen->gi_frame);
+
+ if ((fname = strrchr(file, '/')) == NULL)
+ fname = file;
+ else
+ fname++;
+
+ kore_log(LOG_NOTICE, "coro %lld %s <%s> @ [%s:%d]",
+ coro->id, label, func, fname, line);
+}
+#endif
+
static void
pyconnection_dealloc(struct pyconnection *pyc)
{