From 75ec7ce1dc48c5ff212951a80d1161642bf13351 Mon Sep 17 00:00:00 2001 From: Sven Trenkel Date: Mon, 9 Nov 2009 21:49:34 +0100 Subject: [PATCH] Added a config option to start collectd as an interactive python shell. --- src/python.c | 43 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 37 insertions(+), 6 deletions(-) diff --git a/src/python.c b/src/python.c index 0bd2de58..a68e374c 100644 --- a/src/python.c +++ b/src/python.c @@ -1,6 +1,10 @@ #include #include +#if HAVE_PTHREAD_H +# include +#endif + #include "collectd.h" #include "common.h" @@ -13,6 +17,8 @@ typedef struct cpy_callback_s { struct cpy_callback_s *next; } cpy_callback_t; +static int do_interactive = 0; + /* This is our global thread state. Python saves some stuff in thread-local * storage. So if we allow the interpreter to run in the background * (the scriptwriters might have created some threads from python), we have @@ -320,11 +326,11 @@ static PyObject *cpy_Debug(PyObject *self, PyObject *args) { } static PyMethodDef cpy_methods[] = { - {"Debug", cpy_Debug, METH_VARARGS, "This is an unhelpful text."}, - {"Info", cpy_Info, METH_VARARGS, "This is an unhelpful text."}, - {"Notice", cpy_Notice, METH_VARARGS, "This is an unhelpful text."}, - {"Warning", cpy_Warning, METH_VARARGS, "This is an unhelpful text."}, - {"Error", cpy_Error, METH_VARARGS, "This is an unhelpful text."}, + {"debug", cpy_Debug, METH_VARARGS, "This is an unhelpful text."}, + {"info", cpy_Info, METH_VARARGS, "This is an unhelpful text."}, + {"notice", cpy_Notice, METH_VARARGS, "This is an unhelpful text."}, + {"warning", cpy_Warning, METH_VARARGS, "This is an unhelpful text."}, + {"error", cpy_Error, METH_VARARGS, "This is an unhelpful text."}, {"register_log", (PyCFunction) cpy_register_log, METH_VARARGS | METH_KEYWORDS, "This is an unhelpful text."}, {"register_init", (PyCFunction) cpy_register_init, METH_VARARGS | METH_KEYWORDS, "This is an unhelpful text."}, {"register_config", (PyCFunction) cpy_register_config, METH_VARARGS | METH_KEYWORDS, "This is an unhelpful text."}, @@ -353,9 +359,23 @@ static int cpy_shutdown(void) { return 0; } +static void *cpy_interactive(void *data) { + CPY_LOCK_THREADS + if (PyImport_ImportModule("readline") == NULL) { + /* This interactive session will suck. */ + PyErr_Print(); /* FIXME */ + } + PyRun_InteractiveLoop(stdin, ""); + CPY_RELEASE_THREADS + NOTICE("python: Interactive interpreter exited, stopping collectd ..."); + raise(SIGINT); + return NULL; +} + static int cpy_init(void) { cpy_callback_t *c; PyObject *ret; + static pthread_t thread; PyEval_InitThreads(); /* Now it's finally OK to use python threads. */ @@ -367,6 +387,12 @@ static int cpy_init(void) { Py_DECREF(ret); } state = PyEval_SaveThread(); + if (do_interactive) { + if (pthread_create(&thread, NULL, cpy_interactive, NULL)) { + ERROR("python: Error creating thread for interactive interpreter."); + } + } + return 0; } @@ -442,7 +468,12 @@ static int cpy_config(oconfig_item_t *ci) { for (i = 0; i < ci->children_num; ++i) { oconfig_item_t *item = ci->children + i; - if (strcasecmp(item->key, "ModulePath") == 0) { + if (strcasecmp(item->key, "Interactive") == 0) { + if (item->values_num != 1 || item->values[0].type != OCONFIG_TYPE_BOOLEAN || + !item->values[0].value.boolean) + continue; + do_interactive = 1; + } else if (strcasecmp(item->key, "ModulePath") == 0) { char *dir = NULL; PyObject *dir_object; -- 2.30.2