Somewhat workable python3 support. This breaks python2 support and the __repr__ funct...
[collectd.git] / src / python.c
1 /**
2  * collectd - src/python.c
3  * Copyright (C) 2009  Sven Trenkel
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in
13  * all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21  * DEALINGS IN THE SOFTWARE.
22  *
23  * Authors:
24  *   Sven Trenkel <collectd at semidefinite.de>  
25  **/
26
27 #include <Python.h>
28 #include <structmember.h>
29
30 #include <signal.h>
31 #if HAVE_PTHREAD_H
32 # include <pthread.h>
33 #endif
34
35 #include "collectd.h"
36 #include "common.h"
37
38 #include "cpython.h"
39
40 typedef struct cpy_callback_s {
41         char *name;
42         PyObject *callback;
43         PyObject *data;
44         struct cpy_callback_s *next;
45 } cpy_callback_t;
46
47 static char log_doc[] = "This function sends a string to all logging plugins.";
48
49 static char flush_doc[] = "flush([plugin][, timeout][, identifier]) -> None\n"
50                 "\n"
51                 "Flushes the cache of another plugin.";
52
53 static char unregister_doc[] = "Unregisters a callback. This function needs exactly one parameter either\n"
54                 "the function to unregister or the callback identifier to unregister.";
55
56 static char reg_log_doc[] = "register_log(callback[, data][, name]) -> identifier\n"
57                 "\n"
58                 "Register a callback function for log messages.\n"
59                 "\n"
60                 "'callback' is a callable object that will be called every time something\n"
61                 "    is logged.\n"
62                 "'data' is an optional object that will be passed back to the callback\n"
63                 "    function every time it is called.\n"
64                 "'name' is an optional identifier for this callback. The default name\n"
65                 "    is 'python.<module>'.\n"
66                 "    Every callback needs a unique identifier, so if you want to\n"
67                 "    register this callback multiple time from the same module you need\n"
68                 "    to specify a name here.\n"
69                 "'identifier' is the full identifier assigned to this callback.\n"
70                 "\n"
71                 "The callback function will be called with two or three parameters:\n"
72                 "severity: An integer that should be compared to the LOG_ constants.\n"
73                 "message: The text to be logged.\n"
74                 "data: The optional data parameter passed to the register function.\n"
75                 "    If the parameter was omitted it will be omitted here, too.";
76
77 static char reg_init_doc[] = "register_init(callback[, data][, name]) -> identifier\n"
78                 "\n"
79                 "Register a callback function that will be executed once after the config.\n"
80                 "file has been read, all plugins heve been loaded and the collectd has\n"
81                 "forked into the background.\n"
82                 "\n"
83                 "'callback' is a callable object that will be executed.\n"
84                 "'data' is an optional object that will be passed back to the callback\n"
85                 "    function when it is called.\n"
86                 "'name' is an optional identifier for this callback. The default name\n"
87                 "    is 'python.<module>'.\n"
88                 "    Every callback needs a unique identifier, so if you want to\n"
89                 "    register this callback multiple time from the same module you need\n"
90                 "    to specify a name here.\n"
91                 "'identifier' is the full identifier assigned to this callback.\n"
92                 "\n"
93                 "The callback function will be called without parameters, except for\n"
94                 "data if it was supplied.";
95
96 static char reg_config_doc[] = "register_config(callback[, data][, name]) -> identifier\n"
97                 "\n"
98                 "Register a callback function for config file entries.\n"
99                 "'callback' is a callable object that will be called for every config block.\n"
100                 "'data' is an optional object that will be passed back to the callback\n"
101                 "    function every time it is called.\n"
102                 "'name' is an optional identifier for this callback. The default name\n"
103                 "    is 'python.<module>'.\n"
104                 "    Every callback needs a unique identifier, so if you want to\n"
105                 "    register this callback multiple time from the same module you need\n"
106                 "    to specify a name here.\n"
107                 "'identifier' is the full identifier assigned to this callback.\n"
108                 "\n"
109                 "The callback function will be called with one or two parameters:\n"
110                 "config: A Config object.\n"
111                 "data: The optional data parameter passed to the register function.\n"
112                 "    If the parameter was omitted it will be omitted here, too.";
113
114 static char reg_read_doc[] = "register_read(callback[, interval][, data][, name]) -> identifier\n"
115                 "\n"
116                 "Register a callback function for reading data. It will just be called\n"
117                 "in a fixed interval to signal that it's time to dispatch new values.\n"
118                 "'callback' is a callable object that will be called every time something\n"
119                 "    is logged.\n"
120                 "'interval' is the number of seconds between between calls to the callback\n"
121                 "    function. Full float precision is supported here.\n"
122                 "'data' is an optional object that will be passed back to the callback\n"
123                 "    function every time it is called.\n"
124                 "'name' is an optional identifier for this callback. The default name\n"
125                 "    is 'python.<module>'.\n"
126                 "    Every callback needs a unique identifier, so if you want to\n"
127                 "    register this callback multiple time from the same module you need\n"
128                 "    to specify a name here.\n"
129                 "'identifier' is the full identifier assigned to this callback.\n"
130                 "\n"
131                 "The callback function will be called without parameters, except for\n"
132                 "data if it was supplied.";
133
134 static char reg_write_doc[] = "register_write(callback[, data][, name]) -> identifier\n"
135                 "\n"
136                 "Register a callback function to receive values dispatched by other plugins.\n"
137                 "'callback' is a callable object that will be called every time a value\n"
138                 "    is dispatched.\n"
139                 "'data' is an optional object that will be passed back to the callback\n"
140                 "    function every time it is called.\n"
141                 "'name' is an optional identifier for this callback. The default name\n"
142                 "    is 'python.<module>'.\n"
143                 "    Every callback needs a unique identifier, so if you want to\n"
144                 "    register this callback multiple time from the same module you need\n"
145                 "    to specify a name here.\n"
146                 "'identifier' is the full identifier assigned to this callback.\n"
147                 "\n"
148                 "The callback function will be called with one or two parameters:\n"
149                 "values: A Values object which is a copy of the dispatched values.\n"
150                 "data: The optional data parameter passed to the register function.\n"
151                 "    If the parameter was omitted it will be omitted here, too.";
152
153 static char reg_notification_doc[] = "register_notification(callback[, data][, name]) -> identifier\n"
154                 "\n"
155                 "Register a callback function for notifications.\n"
156                 "'callback' is a callable object that will be called every time a notification\n"
157                 "    is dispatched.\n"
158                 "'data' is an optional object that will be passed back to the callback\n"
159                 "    function every time it is called.\n"
160                 "'name' is an optional identifier for this callback. The default name\n"
161                 "    is 'python.<module>'.\n"
162                 "    Every callback needs a unique identifier, so if you want to\n"
163                 "    register this callback multiple time from the same module you need\n"
164                 "    to specify a name here.\n"
165                 "'identifier' is the full identifier assigned to this callback.\n"
166                 "\n"
167                 "The callback function will be called with one or two parameters:\n"
168                 "notification: A copy of the notification that was dispatched.\n"
169                 "data: The optional data parameter passed to the register function.\n"
170                 "    If the parameter was omitted it will be omitted here, too.";
171
172 static char reg_flush_doc[] = "register_flush(callback[, data][, name]) -> identifier\n"
173                 "\n"
174                 "Register a callback function for flush messages.\n"
175                 "'callback' is a callable object that will be called every time a plugin\n"
176                 "    requests a flush for either this or all plugins.\n"
177                 "'data' is an optional object that will be passed back to the callback\n"
178                 "    function every time it is called.\n"
179                 "'name' is an optional identifier for this callback. The default name\n"
180                 "    is 'python.<module>'.\n"
181                 "    Every callback needs a unique identifier, so if you want to\n"
182                 "    register this callback multiple time from the same module you need\n"
183                 "    to specify a name here.\n"
184                 "'identifier' is the full identifier assigned to this callback.\n"
185                 "\n"
186                 "The callback function will be called with two or three parameters:\n"
187                 "timeout: Indicates that only data older than 'timeout' seconds is to\n"
188                 "    be flushed.\n"
189                 "id: Specifies which values are to be flushed.\n"
190                 "data: The optional data parameter passed to the register function.\n"
191                 "    If the parameter was omitted it will be omitted here, too.";
192
193 static char reg_shutdown_doc[] = "register_shutdown(callback[, data][, name]) -> identifier\n"
194                 "\n"
195                 "Register a callback function for collectd shutdown.\n"
196                 "'callback' is a callable object that will be called once collectd is\n"
197                 "    shutting down.\n"
198                 "'data' is an optional object that will be passed back to the callback\n"
199                 "    function if it is called.\n"
200                 "'name' is an optional identifier for this callback. The default name\n"
201                 "    is 'python.<module>'.\n"
202                 "    Every callback needs a unique identifier, so if you want to\n"
203                 "    register this callback multiple time from the same module you need\n"
204                 "    to specify a name here.\n"
205                 "'identifier' is the full identifier assigned to this callback.\n"
206                 "\n"
207                 "The callback function will be called with no parameters except for\n"
208                 "    data if it was supplied.";
209
210
211 static int do_interactive = 0;
212
213 /* This is our global thread state. Python saves some stuff in thread-local
214  * storage. So if we allow the interpreter to run in the background
215  * (the scriptwriters might have created some threads from python), we have
216  * to save the state so we can resume it later after shutdown. */
217
218 static PyThreadState *state;
219
220 static PyObject *cpy_format_exception;
221
222 static cpy_callback_t *cpy_config_callbacks;
223 static cpy_callback_t *cpy_init_callbacks;
224 static cpy_callback_t *cpy_shutdown_callbacks;
225
226 static void cpy_destroy_user_data(void *data) {
227         cpy_callback_t *c = data;
228         free(c->name);
229         Py_DECREF(c->callback);
230         Py_XDECREF(c->data);
231         free(c);
232 }
233
234 /* You must hold the GIL to call this function!
235  * But if you managed to extract the callback parameter then you probably already do. */
236
237 static void cpy_build_name(char *buf, size_t size, PyObject *callback, const char *name) {
238         const char *module = NULL;
239         PyObject *mod = NULL;
240         
241         if (name != NULL) {
242                 snprintf(buf, size, "python.%s", name);
243                 return;
244         }
245         
246         mod = PyObject_GetAttrString(callback, "__module__"); /* New reference. */
247         if (mod != NULL)
248                 module = cpy_unicode_or_bytes_to_string(&mod);
249         
250         if (module != NULL) {
251                 snprintf(buf, size, "python.%s", module);
252                 Py_XDECREF(mod);
253                 PyErr_Clear();
254                 return;
255         }
256         Py_XDECREF(mod);
257         
258         snprintf(buf, size, "python.%p", callback);
259         PyErr_Clear();
260 }
261
262 static void cpy_log_exception(const char *context) {
263         int l = 0, i;
264         const char *typename = NULL, *message = NULL;
265         PyObject *type, *value, *traceback, *tn, *m, *list;
266         
267         PyErr_Fetch(&type, &value, &traceback);
268         PyErr_NormalizeException(&type, &value, &traceback);
269         if (type == NULL) return;
270         tn = PyObject_GetAttrString(type, "__name__"); /* New reference. */
271         m = PyObject_Str(value); /* New reference. */
272         if (tn != NULL)
273                 typename = cpy_unicode_or_bytes_to_string(&tn);
274         if (m != NULL)
275                 message = cpy_unicode_or_bytes_to_string(&m);
276         if (typename == NULL)
277                 typename = "NamelessException";
278         if (message == NULL)
279                 message = "N/A";
280         Py_BEGIN_ALLOW_THREADS
281         ERROR("Unhandled python exception in %s: %s: %s", context, typename, message);
282         Py_END_ALLOW_THREADS
283         Py_XDECREF(tn);
284         Py_XDECREF(m);
285         if (!cpy_format_exception) {
286                 PyErr_Clear();
287                 Py_XDECREF(type);
288                 Py_XDECREF(value);
289                 Py_XDECREF(traceback);
290                 return;
291         }
292         if (!traceback) {
293                 PyErr_Clear();
294                 return;
295         }
296         list = PyObject_CallFunction(cpy_format_exception, "NNN", type, value, traceback); /* New reference. */
297         if (list)
298                 l = PyObject_Length(list);
299         for (i = 0; i < l; ++i) {
300                 char *s;
301                 PyObject *line;
302                 
303                 line = PyList_GET_ITEM(list, i); /* Borrowed reference. */
304                 Py_INCREF(line);
305                 s = strdup(cpy_unicode_or_bytes_to_string(&line));
306                 Py_DECREF(line);
307                 if (s[strlen(s) - 1] == '\n')
308                         s[strlen(s) - 1] = 0;
309                 Py_BEGIN_ALLOW_THREADS
310                 ERROR("%s", s);
311                 Py_END_ALLOW_THREADS
312                 free(s);
313         }
314         Py_XDECREF(list);
315         PyErr_Clear();
316 }
317
318 static int cpy_read_callback(user_data_t *data) {
319         cpy_callback_t *c = data->data;
320         PyObject *ret;
321
322         CPY_LOCK_THREADS
323                 ret = PyObject_CallFunctionObjArgs(c->callback, c->data, (void *) 0); /* New reference. */
324                 if (ret == NULL) {
325                         cpy_log_exception("read callback");
326                 } else {
327                         Py_DECREF(ret);
328                 }
329         CPY_RELEASE_THREADS
330         if (ret == NULL)
331                 return 1;
332         return 0;
333 }
334
335 static int cpy_write_callback(const data_set_t *ds, const value_list_t *value_list, user_data_t *data) {
336         int i;
337         cpy_callback_t *c = data->data;
338         PyObject *ret, *v, *list;
339
340         CPY_LOCK_THREADS
341                 list = PyList_New(value_list->values_len); /* New reference. */
342                 if (list == NULL) {
343                         cpy_log_exception("write callback");
344                         CPY_RETURN_FROM_THREADS 0;
345                 }
346                 for (i = 0; i < value_list->values_len; ++i) {
347                         if (ds->ds->type == DS_TYPE_COUNTER) {
348                                 if ((long) value_list->values[i].counter == value_list->values[i].counter)
349                                         PyList_SetItem(list, i, PyInt_FromLong(value_list->values[i].counter));
350                                 else
351                                         PyList_SetItem(list, i, PyLong_FromUnsignedLongLong(value_list->values[i].counter));
352                         } else if (ds->ds->type == DS_TYPE_GAUGE) {
353                                 PyList_SetItem(list, i, PyFloat_FromDouble(value_list->values[i].gauge));
354                         } else if (ds->ds->type == DS_TYPE_DERIVE) {
355                                 if ((long) value_list->values[i].derive == value_list->values[i].derive)
356                                         PyList_SetItem(list, i, PyInt_FromLong(value_list->values[i].derive));
357                                 else
358                                         PyList_SetItem(list, i, PyLong_FromLongLong(value_list->values[i].derive));
359                         } else if (ds->ds->type == DS_TYPE_ABSOLUTE) {
360                                 if ((long) value_list->values[i].absolute == value_list->values[i].absolute)
361                                         PyList_SetItem(list, i, PyInt_FromLong(value_list->values[i].absolute));
362                                 else
363                                         PyList_SetItem(list, i, PyLong_FromUnsignedLongLong(value_list->values[i].absolute));
364                         } else {
365                                 Py_BEGIN_ALLOW_THREADS
366                                 ERROR("cpy_write_callback: Unknown value type %d.", ds->ds->type);
367                                 Py_END_ALLOW_THREADS
368                                 Py_DECREF(list);
369                                 CPY_RETURN_FROM_THREADS 0;
370                         }
371                         if (PyErr_Occurred() != NULL) {
372                                 cpy_log_exception("value building for write callback");
373                                 CPY_RETURN_FROM_THREADS 0;
374                         }
375                 }
376                 v = PyObject_CallFunction((void *) &ValuesType, "sOssssdi", value_list->type, list,
377                                 value_list->plugin_instance, value_list->type_instance, value_list->plugin,
378                                 value_list->host, (double) value_list->time, value_list->interval);
379                 Py_DECREF(list);
380                 ret = PyObject_CallFunctionObjArgs(c->callback, v, c->data, (void *) 0); /* New reference. */
381                 if (ret == NULL) {
382                         cpy_log_exception("write callback");
383                 } else {
384                         Py_DECREF(ret);
385                 }
386         CPY_RELEASE_THREADS
387         return 0;
388 }
389
390 static int cpy_notification_callback(const notification_t *notification, user_data_t *data) {
391         cpy_callback_t *c = data->data;
392         PyObject *ret, *n;
393
394         CPY_LOCK_THREADS
395                 n = PyObject_CallFunction((void *) &NotificationType, "ssssssdi", notification->type, notification->message,
396                                 notification->plugin_instance, notification->type_instance, notification->plugin,
397                                 notification->host, (double) notification->time, notification->severity);
398                 ret = PyObject_CallFunctionObjArgs(c->callback, n, c->data, (void *) 0); /* New reference. */
399                 if (ret == NULL) {
400                         cpy_log_exception("notification callback");
401                 } else {
402                         Py_DECREF(ret);
403                 }
404         CPY_RELEASE_THREADS
405         return 0;
406 }
407
408 static void cpy_log_callback(int severity, const char *message, user_data_t *data) {
409         cpy_callback_t * c = data->data;
410         PyObject *ret;
411
412         CPY_LOCK_THREADS
413         if (c->data == NULL)
414                 ret = PyObject_CallFunction(c->callback, "is", severity, message); /* New reference. */
415         else
416                 ret = PyObject_CallFunction(c->callback, "isO", severity, message, c->data); /* New reference. */
417
418         if (ret == NULL) {
419                 /* FIXME */
420                 /* Do we really want to trigger a log callback because a log callback failed?
421                  * Probably not. */
422                 PyErr_Print();
423                 /* In case someone wanted to be clever, replaced stderr and failed at that. */
424                 PyErr_Clear();
425         } else {
426                 Py_DECREF(ret);
427         }
428         CPY_RELEASE_THREADS
429 }
430
431 static void cpy_flush_callback(int timeout, const char *id, user_data_t *data) {
432         cpy_callback_t * c = data->data;
433         PyObject *ret;
434
435         CPY_LOCK_THREADS
436         if (c->data == NULL)
437                 ret = PyObject_CallFunction(c->callback, "is", timeout, id); /* New reference. */
438         else
439                 ret = PyObject_CallFunction(c->callback, "isO", timeout, id, c->data); /* New reference. */
440
441         if (ret == NULL) {
442                 cpy_log_exception("flush callback");
443         } else {
444                 Py_DECREF(ret);
445         }
446         CPY_RELEASE_THREADS
447 }
448
449 static PyObject *cpy_register_generic(cpy_callback_t **list_head, PyObject *args, PyObject *kwds) {
450         char buf[512];
451         cpy_callback_t *c;
452         const char *name = NULL;
453         PyObject *callback = NULL, *data = NULL, *mod = NULL;
454         static char *kwlist[] = {"callback", "data", "name", NULL};
455         
456         if (PyArg_ParseTupleAndKeywords(args, kwds, "O|Oz", kwlist, &callback, &data, &name) == 0) return NULL;
457         if (PyCallable_Check(callback) == 0) {
458                 PyErr_SetString(PyExc_TypeError, "callback needs a be a callable object.");
459                 return NULL;
460         }
461         cpy_build_name(buf, sizeof(buf), callback, name);
462
463         Py_INCREF(callback);
464         Py_XINCREF(data);
465         c = malloc(sizeof(*c));
466         c->name = strdup(buf);
467         c->callback = callback;
468         c->data = data;
469         c->next = *list_head;
470         *list_head = c;
471         Py_XDECREF(mod);
472         return cpy_string_to_unicode_or_bytes(buf);
473 }
474
475 static PyObject *cpy_flush(cpy_callback_t **list_head, PyObject *args, PyObject *kwds) {
476         int timeout = -1;
477         const char *plugin = NULL, *identifier = NULL;
478         static char *kwlist[] = {"plugin", "timeout", "identifier", NULL};
479         
480         if (PyArg_ParseTupleAndKeywords(args, kwds, "|ziz", kwlist, &plugin, &timeout, &identifier) == 0) return NULL;
481         Py_BEGIN_ALLOW_THREADS
482         plugin_flush(plugin, timeout, identifier);
483         Py_END_ALLOW_THREADS
484         Py_RETURN_NONE;
485 }
486
487 static PyObject *cpy_register_config(PyObject *self, PyObject *args, PyObject *kwds) {
488         return cpy_register_generic(&cpy_config_callbacks, args, kwds);
489 }
490
491 static PyObject *cpy_register_init(PyObject *self, PyObject *args, PyObject *kwds) {
492         return cpy_register_generic(&cpy_init_callbacks, args, kwds);
493 }
494
495 typedef int reg_function_t(const char *name, void *callback, void *data);
496
497 static PyObject *cpy_register_generic_userdata(void *reg, void *handler, PyObject *args, PyObject *kwds) {
498         char buf[512];
499         reg_function_t *register_function = (reg_function_t *) reg;
500         cpy_callback_t *c = NULL;
501         user_data_t *user_data = NULL;
502         const char *name = NULL;
503         PyObject *callback = NULL, *data = NULL;
504         static char *kwlist[] = {"callback", "data", "name", NULL};
505         
506         if (PyArg_ParseTupleAndKeywords(args, kwds, "O|Oz", kwlist, &callback, &data, &name) == 0) return NULL;
507         if (PyCallable_Check(callback) == 0) {
508                 PyErr_SetString(PyExc_TypeError, "callback needs a be a callable object.");
509                 return NULL;
510         }
511         cpy_build_name(buf, sizeof(buf), callback, name);
512         
513         Py_INCREF(callback);
514         Py_XINCREF(data);
515         c = malloc(sizeof(*c));
516         c->name = strdup(buf);
517         c->callback = callback;
518         c->data = data;
519         c->next = NULL;
520         user_data = malloc(sizeof(*user_data));
521         user_data->free_func = cpy_destroy_user_data;
522         user_data->data = c;
523         register_function(buf, handler, user_data);
524         return cpy_string_to_unicode_or_bytes(buf);
525 }
526
527 static PyObject *cpy_register_read(PyObject *self, PyObject *args, PyObject *kwds) {
528         char buf[512];
529         cpy_callback_t *c = NULL;
530         user_data_t *user_data = NULL;
531         double interval = 0;
532         const char *name = NULL;
533         PyObject *callback = NULL, *data = NULL;
534         struct timespec ts;
535         static char *kwlist[] = {"callback", "interval", "data", "name", NULL};
536         
537         if (PyArg_ParseTupleAndKeywords(args, kwds, "O|dOz", kwlist, &callback, &interval, &data, &name) == 0) return NULL;
538         if (PyCallable_Check(callback) == 0) {
539                 PyErr_SetString(PyExc_TypeError, "callback needs a be a callable object.");
540                 return NULL;
541         }
542         cpy_build_name(buf, sizeof(buf), callback, name);
543         
544         Py_INCREF(callback);
545         Py_XINCREF(data);
546         c = malloc(sizeof(*c));
547         c->name = strdup(buf);
548         c->callback = callback;
549         c->data = data;
550         c->next = NULL;
551         user_data = malloc(sizeof(*user_data));
552         user_data->free_func = cpy_destroy_user_data;
553         user_data->data = c;
554         ts.tv_sec = interval;
555         ts.tv_nsec = (interval - ts.tv_sec) * 1000000000;
556         plugin_register_complex_read(buf, cpy_read_callback, &ts, user_data);
557         return cpy_string_to_unicode_or_bytes(buf);
558 }
559
560 static PyObject *cpy_register_log(PyObject *self, PyObject *args, PyObject *kwds) {
561         return cpy_register_generic_userdata((void *) plugin_register_log,
562                         (void *) cpy_log_callback, args, kwds);
563 }
564
565 static PyObject *cpy_register_write(PyObject *self, PyObject *args, PyObject *kwds) {
566         return cpy_register_generic_userdata((void *) plugin_register_write,
567                         (void *) cpy_write_callback, args, kwds);
568 }
569
570 static PyObject *cpy_register_notification(PyObject *self, PyObject *args, PyObject *kwds) {
571         return cpy_register_generic_userdata((void *) plugin_register_notification,
572                         (void *) cpy_notification_callback, args, kwds);
573 }
574
575 static PyObject *cpy_register_flush(PyObject *self, PyObject *args, PyObject *kwds) {
576         return cpy_register_generic_userdata((void *) plugin_register_flush,
577                         (void *) cpy_flush_callback, args, kwds);
578 }
579
580 static PyObject *cpy_register_shutdown(PyObject *self, PyObject *args, PyObject *kwds) {
581         return cpy_register_generic(&cpy_shutdown_callbacks, args, kwds);
582 }
583
584 static PyObject *cpy_error(PyObject *self, PyObject *args) {
585         const char *text;
586         if (PyArg_ParseTuple(args, "s", &text) == 0) return NULL;
587         Py_BEGIN_ALLOW_THREADS
588         plugin_log(LOG_ERR, "%s", text);
589         Py_END_ALLOW_THREADS
590         Py_RETURN_NONE;
591 }
592
593 static PyObject *cpy_warning(PyObject *self, PyObject *args) {
594         const char *text;
595         if (PyArg_ParseTuple(args, "s", &text) == 0) return NULL;
596         Py_BEGIN_ALLOW_THREADS
597         plugin_log(LOG_WARNING, "%s", text);
598         Py_END_ALLOW_THREADS
599         Py_RETURN_NONE;
600 }
601
602 static PyObject *cpy_notice(PyObject *self, PyObject *args) {
603         const char *text;
604         if (PyArg_ParseTuple(args, "s", &text) == 0) return NULL;
605         Py_BEGIN_ALLOW_THREADS
606         plugin_log(LOG_NOTICE, "%s", text);
607         Py_END_ALLOW_THREADS
608         Py_RETURN_NONE;
609 }
610
611 static PyObject *cpy_info(PyObject *self, PyObject *args) {
612         const char *text;
613         if (PyArg_ParseTuple(args, "s", &text) == 0) return NULL;
614         Py_BEGIN_ALLOW_THREADS
615         plugin_log(LOG_INFO, "%s", text);
616         Py_END_ALLOW_THREADS
617         Py_RETURN_NONE;
618 }
619
620 static PyObject *cpy_debug(PyObject *self, PyObject *args) {
621 #ifdef COLLECT_DEBUG
622         const char *text;
623         if (PyArg_ParseTuple(args, "s", &text) == 0) return NULL;
624         Py_BEGIN_ALLOW_THREADS
625         plugin_log(LOG_DEBUG, "%s", text);
626         Py_END_ALLOW_THREADS
627 #endif
628         Py_RETURN_NONE;
629 }
630
631 static PyObject *cpy_unregister_generic(cpy_callback_t **list_head, PyObject *arg, const char *desc) {
632         char buf[512];
633         const char *name;
634         cpy_callback_t *prev = NULL, *tmp;
635
636         Py_INCREF(arg);
637         name = cpy_unicode_or_bytes_to_string(&arg);
638         if (name == NULL) {
639                 PyErr_Clear();
640                 if (!PyCallable_Check(arg)) {
641                         PyErr_SetString(PyExc_TypeError, "This function needs a string or a callable object as its only parameter.");
642                         Py_DECREF(arg);
643                         return NULL;
644                 }
645                 cpy_build_name(buf, sizeof(buf), arg, NULL);
646                 name = buf;
647         }
648         for (tmp = *list_head; tmp; prev = tmp, tmp = tmp->next)
649                 if (strcmp(name, tmp->name) == 0)
650                         break;
651         
652         Py_DECREF(arg);
653         if (tmp == NULL) {
654                 PyErr_Format(PyExc_RuntimeError, "Unable to unregister %s callback '%s'.", desc, name);
655                 return NULL;
656         }
657         /* Yes, this is actually save. To call this function the caller has to
658          * hold the GIL. Well, save as long as there is only one GIL anyway ... */
659         if (prev == NULL)
660                 *list_head = tmp->next;
661         else
662                 prev->next = tmp->next;
663         cpy_destroy_user_data(tmp);
664         Py_RETURN_NONE;
665 }
666
667 typedef int cpy_unregister_function_t(const char *name);
668
669 static PyObject *cpy_unregister_generic_userdata(cpy_unregister_function_t *unreg, PyObject *arg, const char *desc) {
670         char buf[512];
671         const char *name;
672
673         Py_INCREF(arg);
674         name = cpy_unicode_or_bytes_to_string(&arg);
675         if (name == NULL) {
676                 PyErr_Clear();
677                 if (!PyCallable_Check(arg)) {
678                         PyErr_SetString(PyExc_TypeError, "This function needs a string or a callable object as its only parameter.");
679                         Py_DECREF(&arg);
680                         return NULL;
681                 }
682                 cpy_build_name(buf, sizeof(buf), arg, NULL);
683                 name = buf;
684         }
685         if (unreg(name) == 0) {
686                 Py_DECREF(&arg);
687                 Py_RETURN_NONE;
688         }
689         PyErr_Format(PyExc_RuntimeError, "Unable to unregister %s callback '%s'.", desc, name);
690         Py_DECREF(&arg);
691         return NULL;
692 }
693
694 static PyObject *cpy_unregister_log(PyObject *self, PyObject *arg) {
695         return cpy_unregister_generic_userdata(plugin_unregister_log, arg, "log");
696 }
697
698 static PyObject *cpy_unregister_init(PyObject *self, PyObject *arg) {
699         return cpy_unregister_generic(&cpy_init_callbacks, arg, "init");
700 }
701
702 static PyObject *cpy_unregister_config(PyObject *self, PyObject *arg) {
703         return cpy_unregister_generic(&cpy_config_callbacks, arg, "config");
704 }
705
706 static PyObject *cpy_unregister_read(PyObject *self, PyObject *arg) {
707         return cpy_unregister_generic_userdata(plugin_unregister_read, arg, "read");
708 }
709
710 static PyObject *cpy_unregister_write(PyObject *self, PyObject *arg) {
711         return cpy_unregister_generic_userdata(plugin_unregister_write, arg, "write");
712 }
713
714 static PyObject *cpy_unregister_notification(PyObject *self, PyObject *arg) {
715         return cpy_unregister_generic_userdata(plugin_unregister_notification, arg, "notification");
716 }
717
718 static PyObject *cpy_unregister_flush(PyObject *self, PyObject *arg) {
719         return cpy_unregister_generic_userdata(plugin_unregister_flush, arg, "flush");
720 }
721
722 static PyObject *cpy_unregister_shutdown(PyObject *self, PyObject *arg) {
723         return cpy_unregister_generic(&cpy_shutdown_callbacks, arg, "shutdown");
724 }
725
726 static PyMethodDef cpy_methods[] = {
727         {"debug", cpy_debug, METH_VARARGS, log_doc},
728         {"info", cpy_info, METH_VARARGS, log_doc},
729         {"notice", cpy_notice, METH_VARARGS, log_doc},
730         {"warning", cpy_warning, METH_VARARGS, log_doc},
731         {"error", cpy_error, METH_VARARGS, log_doc},
732         {"flush", (PyCFunction) cpy_flush, METH_VARARGS | METH_KEYWORDS, flush_doc},
733         {"register_log", (PyCFunction) cpy_register_log, METH_VARARGS | METH_KEYWORDS, reg_log_doc},
734         {"register_init", (PyCFunction) cpy_register_init, METH_VARARGS | METH_KEYWORDS, reg_init_doc},
735         {"register_config", (PyCFunction) cpy_register_config, METH_VARARGS | METH_KEYWORDS, reg_config_doc},
736         {"register_read", (PyCFunction) cpy_register_read, METH_VARARGS | METH_KEYWORDS, reg_read_doc},
737         {"register_write", (PyCFunction) cpy_register_write, METH_VARARGS | METH_KEYWORDS, reg_write_doc},
738         {"register_notification", (PyCFunction) cpy_register_notification, METH_VARARGS | METH_KEYWORDS, reg_notification_doc},
739         {"register_flush", (PyCFunction) cpy_register_flush, METH_VARARGS | METH_KEYWORDS, reg_flush_doc},
740         {"register_shutdown", (PyCFunction) cpy_register_shutdown, METH_VARARGS | METH_KEYWORDS, reg_shutdown_doc},
741         {"unregister_log", cpy_unregister_log, METH_O, unregister_doc},
742         {"unregister_init", cpy_unregister_init, METH_O, unregister_doc},
743         {"unregister_config", cpy_unregister_config, METH_O, unregister_doc},
744         {"unregister_read", cpy_unregister_read, METH_O, unregister_doc},
745         {"unregister_write", cpy_unregister_write, METH_O, unregister_doc},
746         {"unregister_notification", cpy_unregister_notification, METH_O, unregister_doc},
747         {"unregister_flush", cpy_unregister_flush, METH_O, unregister_doc},
748         {"unregister_shutdown", cpy_unregister_shutdown, METH_O, unregister_doc},
749         {0, 0, 0, 0}
750 };
751
752 static int cpy_shutdown(void) {
753         cpy_callback_t *c;
754         PyObject *ret;
755         
756         /* This can happen if the module was loaded but not configured. */
757         if (state != NULL)
758                 PyEval_RestoreThread(state);
759
760         for (c = cpy_shutdown_callbacks; c; c = c->next) {
761                 ret = PyObject_CallFunctionObjArgs(c->callback, c->data, (void *) 0); /* New reference. */
762                 if (ret == NULL)
763                         cpy_log_exception("shutdown callback");
764                 else
765                         Py_DECREF(ret);
766         }
767         PyErr_Print();
768         Py_Finalize();
769         return 0;
770 }
771
772 static void cpy_int_handler(int sig) {
773         return;
774 }
775
776 static void *cpy_interactive(void *data) {
777         sigset_t sigset;
778         struct sigaction sig_int_action, old;
779         
780         /* Signal handler in a plugin? Bad stuff, but the best way to
781          * handle it I guess. In an interactive session people will
782          * press Ctrl+C at some time, which will generate a SIGINT.
783          * This will cause collectd to shutdown, thus killing the
784          * interactive interpreter, and leaving the terminal in a
785          * mess. Chances are, this isn't what the user wanted to do.
786          * 
787          * So this is the plan:
788          * 1. Block SIGINT in the main thread.
789          * 2. Install our own signal handler that does nothing.
790          * 3. Unblock SIGINT in the interactive thread.
791          *
792          * This will make sure that SIGINT won't kill collectd but
793          * still interrupt syscalls like sleep and pause.
794          * It does not raise a KeyboardInterrupt exception because so
795          * far nobody managed to figure out how to do that. */
796         memset (&sig_int_action, '\0', sizeof (sig_int_action));
797         sig_int_action.sa_handler = cpy_int_handler;
798         sigaction (SIGINT, &sig_int_action, &old);
799         
800         sigemptyset(&sigset);
801         sigaddset(&sigset, SIGINT);
802         pthread_sigmask(SIG_UNBLOCK, &sigset, NULL);
803         PyEval_AcquireThread(state);
804         if (PyImport_ImportModule("readline") == NULL) {
805                 /* This interactive session will suck. */
806                 cpy_log_exception("interactive session init");
807         }
808         PyRun_InteractiveLoop(stdin, "<stdin>");
809         PyErr_Print();
810         PyEval_ReleaseThread(state);
811         NOTICE("python: Interactive interpreter exited, stopping collectd ...");
812         /* Restore the original collectd SIGINT handler and raise SIGINT.
813          * The main thread still has SIGINT blocked and there's nothing we
814          * can do about that so this thread will handle it. But that's not
815          * important, except that it won't interrupt the main loop and so
816          * it might take a few seconds before collectd really shuts down. */
817         sigaction (SIGINT, &old, NULL);
818         raise(SIGINT);
819         pause();
820         return NULL;
821 }
822
823 static int cpy_init(void) {
824         cpy_callback_t *c;
825         PyObject *ret;
826         static pthread_t thread;
827         sigset_t sigset;
828         
829         PyEval_InitThreads();
830         /* Now it's finally OK to use python threads. */
831         for (c = cpy_init_callbacks; c; c = c->next) {
832                 ret = PyObject_CallFunctionObjArgs(c->callback, c->data, (void *) 0); /* New reference. */
833                 if (ret == NULL)
834                         cpy_log_exception("init callback");
835                 else
836                         Py_DECREF(ret);
837         }
838         sigemptyset(&sigset);
839         sigaddset(&sigset, SIGINT);
840         pthread_sigmask(SIG_BLOCK, &sigset, NULL);
841         state = PyEval_SaveThread();
842         if (do_interactive) {
843                 if (pthread_create(&thread, NULL, cpy_interactive, NULL)) {
844                         ERROR("python: Error creating thread for interactive interpreter.");
845                 }
846         }
847
848         return 0;
849 }
850
851 static PyObject *cpy_oconfig_to_pyconfig(oconfig_item_t *ci, PyObject *parent) {
852         int i;
853         PyObject *item, *values, *children, *tmp;
854         
855         if (parent == NULL)
856                 parent = Py_None;
857         
858         values = PyTuple_New(ci->values_num); /* New reference. */
859         for (i = 0; i < ci->values_num; ++i) {
860                 if (ci->values[i].type == OCONFIG_TYPE_STRING) {
861                         PyTuple_SET_ITEM(values, i, cpy_string_to_unicode_or_bytes(ci->values[i].value.string));
862                 } else if (ci->values[i].type == OCONFIG_TYPE_NUMBER) {
863                         PyTuple_SET_ITEM(values, i, PyFloat_FromDouble(ci->values[i].value.number));
864                 } else if (ci->values[i].type == OCONFIG_TYPE_BOOLEAN) {
865                         PyTuple_SET_ITEM(values, i, PyBool_FromLong(ci->values[i].value.boolean));
866                 }
867         }
868         
869         item = PyObject_CallFunction((void *) &ConfigType, "sONO", ci->key, parent, values, Py_None);
870         if (item == NULL)
871                 return NULL;
872         children = PyTuple_New(ci->children_num); /* New reference. */
873         for (i = 0; i < ci->children_num; ++i) {
874                 PyTuple_SET_ITEM(children, i, cpy_oconfig_to_pyconfig(ci->children + i, item));
875         }
876         tmp = ((Config *) item)->children;
877         ((Config *) item)->children = children;
878         Py_XDECREF(tmp);
879         return item;
880 }
881
882 static struct PyModuleDef collectdmodule = {
883         PyModuleDef_HEAD_INIT,
884         "collectd",   /* name of module */
885         "Where does this go?", /* module documentation, may be NULL */
886         -1,
887         cpy_methods
888 };
889
890 PyMODINIT_FUNC PyInit_collectd(void) {
891         return PyModule_Create(&collectdmodule);
892 }
893
894 static int cpy_config(oconfig_item_t *ci) {
895         int i;
896         PyObject *sys, *tb;
897         PyObject *sys_path;
898         PyObject *module;
899         
900         /* Ok in theory we shouldn't do initialization at this point
901          * but we have to. In order to give python scripts a chance
902          * to register a config callback we need to be able to execute
903          * python code during the config callback so we have to start
904          * the interpreter here. */
905         /* Do *not* use the python "thread" module at this point! */
906
907 #ifdef IS_PY3K
908         /* Add a builtin module, before Py_Initialize */
909         PyImport_AppendInittab("collectd", PyInit_collectd);
910 #endif
911         
912         Py_Initialize();
913         
914         PyType_Ready(&ConfigType);
915         PyType_Ready(&PluginDataType);
916         ValuesType.tp_base = &PluginDataType;
917         PyType_Ready(&ValuesType);
918         NotificationType.tp_base = &PluginDataType;
919         PyType_Ready(&NotificationType);
920         sys = PyImport_ImportModule("sys"); /* New reference. */
921         if (sys == NULL) {
922                 cpy_log_exception("python initialization");
923                 return 1;
924         }
925         sys_path = PyObject_GetAttrString(sys, "path"); /* New reference. */
926         Py_DECREF(sys);
927         if (sys_path == NULL) {
928                 cpy_log_exception("python initialization");
929                 return 1;
930         }
931 #ifdef IS_PY3K
932         module = PyImport_ImportModule("collectd");
933 #else
934         module = Py_InitModule("collectd", cpy_methods); /* Borrowed reference. */
935 #endif
936         PyModule_AddObject(module, "Config", (void *) &ConfigType); /* Steals a reference. */
937         PyModule_AddObject(module, "Values", (void *) &ValuesType); /* Steals a reference. */
938         PyModule_AddObject(module, "Notification", (void *) &NotificationType); /* Steals a reference. */
939         PyModule_AddIntConstant(module, "LOG_DEBUG", LOG_DEBUG);
940         PyModule_AddIntConstant(module, "LOG_INFO", LOG_INFO);
941         PyModule_AddIntConstant(module, "LOG_NOTICE", LOG_NOTICE);
942         PyModule_AddIntConstant(module, "LOG_WARNING", LOG_WARNING);
943         PyModule_AddIntConstant(module, "LOG_ERROR", LOG_ERR);
944         PyModule_AddIntConstant(module, "NOTIF_FAILURE", NOTIF_FAILURE);
945         PyModule_AddIntConstant(module, "NOTIF_WARNING", NOTIF_WARNING);
946         PyModule_AddIntConstant(module, "NOTIF_OKAY", NOTIF_OKAY);
947         for (i = 0; i < ci->children_num; ++i) {
948                 oconfig_item_t *item = ci->children + i;
949                 
950                 if (strcasecmp(item->key, "Interactive") == 0) {
951                         if (item->values_num != 1 || item->values[0].type != OCONFIG_TYPE_BOOLEAN)
952                                 continue;
953                         do_interactive = item->values[0].value.boolean;
954                 } else if (strcasecmp(item->key, "Encoding") == 0) {
955                         if (item->values_num != 1 || item->values[0].type != OCONFIG_TYPE_STRING)
956                                 continue;
957                         /* Why is this even necessary? And undocumented? */
958                         if (PyUnicode_SetDefaultEncoding(item->values[0].value.string))
959                                 cpy_log_exception("setting default encoding");
960                 } else if (strcasecmp(item->key, "LogTraces") == 0) {
961                         if (item->values_num != 1 || item->values[0].type != OCONFIG_TYPE_BOOLEAN)
962                                 continue;
963                         if (!item->values[0].value.boolean) {
964                                 Py_XDECREF(cpy_format_exception);
965                                 cpy_format_exception = NULL;
966                                 continue;
967                         }
968                         if (cpy_format_exception)
969                                 continue;
970                         tb = PyImport_ImportModule("traceback"); /* New reference. */
971                         if (tb == NULL) {
972                                 cpy_log_exception("python initialization");
973                                 continue;
974                         }
975                         cpy_format_exception = PyObject_GetAttrString(tb, "format_exception"); /* New reference. */
976                         Py_DECREF(tb);
977                         if (cpy_format_exception == NULL)
978                                 cpy_log_exception("python initialization");
979                 } else if (strcasecmp(item->key, "ModulePath") == 0) {
980                         char *dir = NULL;
981                         PyObject *dir_object;
982                         
983                         if (cf_util_get_string(item, &dir) != 0) 
984                                 continue;
985                         dir_object = cpy_string_to_unicode_or_bytes(dir); /* New reference. */
986                         if (dir_object == NULL) {
987                                 ERROR("python plugin: Unable to convert \"%s\" to "
988                                       "a python object.", dir);
989                                 free(dir);
990                                 cpy_log_exception("python initialization");
991                                 continue;
992                         }
993                         if (PyList_Append(sys_path, dir_object) != 0) {
994                                 ERROR("python plugin: Unable to append \"%s\" to "
995                                       "python module path.", dir);
996                                 cpy_log_exception("python initialization");
997                         }
998                         Py_DECREF(dir_object);
999                         free(dir);
1000                 } else if (strcasecmp(item->key, "Import") == 0) {
1001                         char *module_name = NULL;
1002                         PyObject *module;
1003                         
1004                         if (cf_util_get_string(item, &module_name) != 0) 
1005                                 continue;
1006                         module = PyImport_ImportModule(module_name); /* New reference. */
1007                         if (module == NULL) {
1008                                 ERROR("python plugin: Error importing module \"%s\".", module_name);
1009                                 cpy_log_exception("importing module");
1010                         }
1011                         free(module_name);
1012                         Py_XDECREF(module);
1013                 } else if (strcasecmp(item->key, "Module") == 0) {
1014                         char *name = NULL;
1015                         cpy_callback_t *c;
1016                         PyObject *ret;
1017                         
1018                         if (cf_util_get_string(item, &name) != 0)
1019                                 continue;
1020                         for (c = cpy_config_callbacks; c; c = c->next) {
1021                                 if (strcasecmp(c->name + 7, name) == 0)
1022                                         break;
1023                         }
1024                         if (c == NULL) {
1025                                 WARNING("python plugin: Found a configuration for the \"%s\" plugin, "
1026                                         "but the plugin isn't loaded or didn't register "
1027                                         "a configuration callback.", name);
1028                                 free(name);
1029                                 continue;
1030                         }
1031                         free(name);
1032                         if (c->data == NULL)
1033                                 ret = PyObject_CallFunction(c->callback, "N",
1034                                         cpy_oconfig_to_pyconfig(item, NULL)); /* New reference. */
1035                         else
1036                                 ret = PyObject_CallFunction(c->callback, "NO",
1037                                         cpy_oconfig_to_pyconfig(item, NULL), c->data); /* New reference. */
1038                         if (ret == NULL)
1039                                 cpy_log_exception("loading module");
1040                         else
1041                                 Py_DECREF(ret);
1042                 } else {
1043                         WARNING("python plugin: Ignoring unknown config key \"%s\".", item->key);
1044                 }
1045         }
1046         Py_DECREF(sys_path);
1047         return 0;
1048 }
1049
1050 void module_register(void) {
1051         plugin_register_complex_config("python", cpy_config);
1052         plugin_register_init("python", cpy_init);
1053         plugin_register_shutdown("python", cpy_shutdown);
1054 }