diff --git a/include/kore/python_methods.h b/include/kore/python_methods.h index 4e5cbdb..7354903 100644 --- a/include/kore/python_methods.h +++ b/include/kore/python_methods.h @@ -39,6 +39,7 @@ static PyObject *python_kore_bind(PyObject *, PyObject *); static PyObject *python_kore_timer(PyObject *, PyObject *); static PyObject *python_kore_fatal(PyObject *, PyObject *); static PyObject *python_kore_queue(PyObject *, PyObject *); +static PyObject *python_kore_tracer(PyObject *, PyObject *); static PyObject *python_kore_gather(PyObject *, PyObject *); static PyObject *python_kore_fatalx(PyObject *, PyObject *); static PyObject *python_kore_suspend(PyObject *, PyObject *); @@ -66,6 +67,7 @@ static struct PyMethodDef pykore_methods[] = { METHOD("bind", python_kore_bind, METH_VARARGS), METHOD("timer", python_kore_timer, METH_VARARGS), METHOD("queue", python_kore_queue, METH_VARARGS), + METHOD("tracer", python_kore_tracer, METH_VARARGS), METHOD("gather", python_kore_gather, METH_VARARGS), METHOD("fatal", python_kore_fatal, METH_VARARGS), METHOD("fatalx", python_kore_fatalx, METH_VARARGS), diff --git a/src/python.c b/src/python.c index cb8b897..62ff4e1 100644 --- a/src/python.c +++ b/src/python.c @@ -171,6 +171,7 @@ extern const char *__progname; /* XXX */ static struct python_coro *coro_running = NULL; +static PyObject *python_tracer = NULL; void kore_python_init(void) @@ -287,7 +288,7 @@ void kore_python_log_error(const char *function) { const char *sval; - PyObject *repr, *type, *value, *traceback; + PyObject *ret, *repr, *type, *value, *traceback; if (!PyErr_Occurred() || PyErr_ExceptionMatches(PyExc_StopIteration)) return; @@ -310,6 +311,13 @@ kore_python_log_error(const char *function) */ if (coro_running != NULL && coro_running->gatherop != NULL) { PyErr_SetObject(PyExc_StopIteration, value); + } else if (python_tracer != NULL) { + /* + * Call the user-supplied tracer callback. + */ + ret = PyObject_CallFunctionObjArgs(python_tracer, + type, value, traceback, NULL); + Py_XDECREF(ret); } else { if ((repr = PyObject_Repr(value)) == NULL) sval = "unknown"; @@ -1027,6 +1035,30 @@ python_kore_queue(PyObject *self, PyObject *args) return ((PyObject *)queue); } +static PyObject * +python_kore_tracer(PyObject *self, PyObject *args) +{ + PyObject *obj; + + if (python_tracer != NULL) { + PyErr_SetString(PyExc_RuntimeError, "tracer already set"); + return (NULL); + } + + if (!PyArg_ParseTuple(args, "O", &obj)) + return (NULL); + + if (!PyCallable_Check(obj)) { + PyErr_SetString(PyExc_RuntimeError, "object not callable"); + Py_DECREF(obj); + return (NULL); + } + + python_tracer = obj; + + Py_RETURN_TRUE; +} + static PyObject * python_kore_gather(PyObject *self, PyObject *args) {