python: Made the plugin unicode save.
[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, *list;
339         Values *v;
340
341         CPY_LOCK_THREADS
342                 list = PyList_New(value_list->values_len); /* New reference. */
343                 if (list == NULL) {
344                         cpy_log_exception("write callback");
345                         CPY_RETURN_FROM_THREADS 0;
346                 }
347                 for (i = 0; i < value_list->values_len; ++i) {
348                         if (ds->ds->type == DS_TYPE_COUNTER) {
349                                 if ((long) value_list->values[i].counter == value_list->values[i].counter)
350                                         PyList_SetItem(list, i, PyInt_FromLong(value_list->values[i].counter));
351                                 else
352                                         PyList_SetItem(list, i, PyLong_FromUnsignedLongLong(value_list->values[i].counter));
353                         } else if (ds->ds->type == DS_TYPE_GAUGE) {
354                                 PyList_SetItem(list, i, PyFloat_FromDouble(value_list->values[i].gauge));
355                         } else if (ds->ds->type == DS_TYPE_DERIVE) {
356                                 if ((long) value_list->values[i].derive == value_list->values[i].derive)
357                                         PyList_SetItem(list, i, PyInt_FromLong(value_list->values[i].derive));
358                                 else
359                                         PyList_SetItem(list, i, PyLong_FromLongLong(value_list->values[i].derive));
360                         } else if (ds->ds->type == DS_TYPE_ABSOLUTE) {
361                                 if ((long) value_list->values[i].absolute == value_list->values[i].absolute)
362                                         PyList_SetItem(list, i, PyInt_FromLong(value_list->values[i].absolute));
363                                 else
364                                         PyList_SetItem(list, i, PyLong_FromUnsignedLongLong(value_list->values[i].absolute));
365                         } else {
366                                 Py_BEGIN_ALLOW_THREADS
367                                 ERROR("cpy_write_callback: Unknown value type %d.", ds->ds->type);
368                                 Py_END_ALLOW_THREADS
369                                 Py_DECREF(list);
370                                 CPY_RETURN_FROM_THREADS 0;
371                         }
372                         if (PyErr_Occurred() != NULL) {
373                                 cpy_log_exception("value building for write callback");
374                                 CPY_RETURN_FROM_THREADS 0;
375                         }
376                 }
377                 v = PyObject_New(Values, (void *) &ValuesType);
378                 sstrncpy(v->data.host, value_list->host, sizeof(v->data.host));
379                 sstrncpy(v->data.type, value_list->type, sizeof(v->data.type));
380                 sstrncpy(v->data.type_instance, value_list->type_instance, sizeof(v->data.type_instance));
381                 sstrncpy(v->data.plugin, value_list->plugin, sizeof(v->data.plugin));
382                 sstrncpy(v->data.plugin_instance, value_list->plugin_instance, sizeof(v->data.plugin_instance));
383                 v->data.time = value_list->time;
384                 v->interval = value_list->interval;
385                 v->values = list;
386                 ret = PyObject_CallFunctionObjArgs(c->callback, v, c->data, (void *) 0); /* New reference. */
387                 if (ret == NULL) {
388                         cpy_log_exception("write callback");
389                 } else {
390                         Py_DECREF(ret);
391                 }
392         CPY_RELEASE_THREADS
393         return 0;
394 }
395
396 static int cpy_notification_callback(const notification_t *notification, user_data_t *data) {
397         cpy_callback_t *c = data->data;
398         PyObject *ret;
399         Notification *n;
400
401         CPY_LOCK_THREADS
402                 n = PyObject_New(Notification, (void *) &NotificationType);
403                 sstrncpy(n->data.host, notification->host, sizeof(n->data.host));
404                 sstrncpy(n->data.type, notification->type, sizeof(n->data.type));
405                 sstrncpy(n->data.type_instance, notification->type_instance, sizeof(n->data.type_instance));
406                 sstrncpy(n->data.plugin, notification->plugin, sizeof(n->data.plugin));
407                 sstrncpy(n->data.plugin_instance, notification->plugin_instance, sizeof(n->data.plugin_instance));
408                 n->data.time = notification->time;
409                 sstrncpy(n->message, notification->message, sizeof(n->message));
410                 n->severity = notification->severity;
411                 ret = PyObject_CallFunctionObjArgs(c->callback, n, c->data, (void *) 0); /* New reference. */
412                 if (ret == NULL) {
413                         cpy_log_exception("notification callback");
414                 } else {
415                         Py_DECREF(ret);
416                 }
417         CPY_RELEASE_THREADS
418         return 0;
419 }
420
421 static void cpy_log_callback(int severity, const char *message, user_data_t *data) {
422         cpy_callback_t * c = data->data;
423         PyObject *ret;
424
425         CPY_LOCK_THREADS
426         if (c->data == NULL)
427                 ret = PyObject_CallFunction(c->callback, "is", severity, message); /* New reference. */
428         else
429                 ret = PyObject_CallFunction(c->callback, "isO", severity, message, c->data); /* New reference. */
430
431         if (ret == NULL) {
432                 /* FIXME */
433                 /* Do we really want to trigger a log callback because a log callback failed?
434                  * Probably not. */
435                 PyErr_Print();
436                 /* In case someone wanted to be clever, replaced stderr and failed at that. */
437                 PyErr_Clear();
438         } else {
439                 Py_DECREF(ret);
440         }
441         CPY_RELEASE_THREADS
442 }
443
444 static void cpy_flush_callback(int timeout, const char *id, user_data_t *data) {
445         cpy_callback_t * c = data->data;
446         PyObject *ret;
447
448         CPY_LOCK_THREADS
449         if (c->data == NULL)
450                 ret = PyObject_CallFunction(c->callback, "is", timeout, id); /* New reference. */
451         else
452                 ret = PyObject_CallFunction(c->callback, "isO", timeout, id, c->data); /* New reference. */
453
454         if (ret == NULL) {
455                 cpy_log_exception("flush callback");
456         } else {
457                 Py_DECREF(ret);
458         }
459         CPY_RELEASE_THREADS
460 }
461
462 static PyObject *cpy_register_generic(cpy_callback_t **list_head, PyObject *args, PyObject *kwds) {
463         char buf[512];
464         cpy_callback_t *c;
465         const char *name = NULL;
466         PyObject *callback = NULL, *data = NULL, *mod = NULL;
467         static char *kwlist[] = {"callback", "data", "name", NULL};
468         
469         if (PyArg_ParseTupleAndKeywords(args, kwds, "O|Oet", kwlist, &callback, &data, NULL, &name) == 0) return NULL;
470         if (PyCallable_Check(callback) == 0) {
471                 PyErr_SetString(PyExc_TypeError, "callback needs a be a callable object.");
472                 return NULL;
473         }
474         cpy_build_name(buf, sizeof(buf), callback, name);
475
476         Py_INCREF(callback);
477         Py_XINCREF(data);
478         c = malloc(sizeof(*c));
479         c->name = strdup(buf);
480         c->callback = callback;
481         c->data = data;
482         c->next = *list_head;
483         *list_head = c;
484         Py_XDECREF(mod);
485         return cpy_string_to_unicode_or_bytes(buf);
486 }
487
488 static PyObject *cpy_flush(cpy_callback_t **list_head, PyObject *args, PyObject *kwds) {
489         int timeout = -1;
490         const char *plugin = NULL, *identifier = NULL;
491         static char *kwlist[] = {"plugin", "timeout", "identifier", NULL};
492         
493         if (PyArg_ParseTupleAndKeywords(args, kwds, "|etiet", kwlist, NULL, &plugin, &timeout, NULL, &identifier) == 0) return NULL;
494         Py_BEGIN_ALLOW_THREADS
495         plugin_flush(plugin, timeout, identifier);
496         Py_END_ALLOW_THREADS
497         Py_RETURN_NONE;
498 }
499
500 static PyObject *cpy_register_config(PyObject *self, PyObject *args, PyObject *kwds) {
501         return cpy_register_generic(&cpy_config_callbacks, args, kwds);
502 }
503
504 static PyObject *cpy_register_init(PyObject *self, PyObject *args, PyObject *kwds) {
505         return cpy_register_generic(&cpy_init_callbacks, args, kwds);
506 }
507
508 typedef int reg_function_t(const char *name, void *callback, void *data);
509
510 static PyObject *cpy_register_generic_userdata(void *reg, void *handler, PyObject *args, PyObject *kwds) {
511         char buf[512];
512         reg_function_t *register_function = (reg_function_t *) reg;
513         cpy_callback_t *c = NULL;
514         user_data_t *user_data = NULL;
515         const char *name = NULL;
516         PyObject *callback = NULL, *data = NULL;
517         static char *kwlist[] = {"callback", "data", "name", NULL};
518         
519         if (PyArg_ParseTupleAndKeywords(args, kwds, "O|Oet", kwlist, &callback, &data, NULL, &name) == 0) return NULL;
520         if (PyCallable_Check(callback) == 0) {
521                 PyErr_SetString(PyExc_TypeError, "callback needs a be a callable object.");
522                 return NULL;
523         }
524         cpy_build_name(buf, sizeof(buf), callback, name);
525         
526         Py_INCREF(callback);
527         Py_XINCREF(data);
528         c = malloc(sizeof(*c));
529         c->name = strdup(buf);
530         c->callback = callback;
531         c->data = data;
532         c->next = NULL;
533         user_data = malloc(sizeof(*user_data));
534         user_data->free_func = cpy_destroy_user_data;
535         user_data->data = c;
536         register_function(buf, handler, user_data);
537         return cpy_string_to_unicode_or_bytes(buf);
538 }
539
540 static PyObject *cpy_register_read(PyObject *self, PyObject *args, PyObject *kwds) {
541         char buf[512];
542         cpy_callback_t *c = NULL;
543         user_data_t *user_data = NULL;
544         double interval = 0;
545         const char *name = NULL;
546         PyObject *callback = NULL, *data = NULL;
547         struct timespec ts;
548         static char *kwlist[] = {"callback", "interval", "data", "name", NULL};
549         
550         if (PyArg_ParseTupleAndKeywords(args, kwds, "O|dOet", kwlist, &callback, &interval, &data, NULL, &name) == 0) return NULL;
551         if (PyCallable_Check(callback) == 0) {
552                 PyErr_SetString(PyExc_TypeError, "callback needs a be a callable object.");
553                 return NULL;
554         }
555         cpy_build_name(buf, sizeof(buf), callback, name);
556         
557         Py_INCREF(callback);
558         Py_XINCREF(data);
559         c = malloc(sizeof(*c));
560         c->name = strdup(buf);
561         c->callback = callback;
562         c->data = data;
563         c->next = NULL;
564         user_data = malloc(sizeof(*user_data));
565         user_data->free_func = cpy_destroy_user_data;
566         user_data->data = c;
567         ts.tv_sec = interval;
568         ts.tv_nsec = (interval - ts.tv_sec) * 1000000000;
569         plugin_register_complex_read(buf, cpy_read_callback, &ts, user_data);
570         return cpy_string_to_unicode_or_bytes(buf);
571 }
572
573 static PyObject *cpy_register_log(PyObject *self, PyObject *args, PyObject *kwds) {
574         return cpy_register_generic_userdata((void *) plugin_register_log,
575                         (void *) cpy_log_callback, args, kwds);
576 }
577
578 static PyObject *cpy_register_write(PyObject *self, PyObject *args, PyObject *kwds) {
579         return cpy_register_generic_userdata((void *) plugin_register_write,
580                         (void *) cpy_write_callback, args, kwds);
581 }
582
583 static PyObject *cpy_register_notification(PyObject *self, PyObject *args, PyObject *kwds) {
584         return cpy_register_generic_userdata((void *) plugin_register_notification,
585                         (void *) cpy_notification_callback, args, kwds);
586 }
587
588 static PyObject *cpy_register_flush(PyObject *self, PyObject *args, PyObject *kwds) {
589         return cpy_register_generic_userdata((void *) plugin_register_flush,
590                         (void *) cpy_flush_callback, args, kwds);
591 }
592
593 static PyObject *cpy_register_shutdown(PyObject *self, PyObject *args, PyObject *kwds) {
594         return cpy_register_generic(&cpy_shutdown_callbacks, args, kwds);
595 }
596
597 static PyObject *cpy_error(PyObject *self, PyObject *args) {
598         const char *text;
599         if (PyArg_ParseTuple(args, "et", NULL, &text) == 0) return NULL;
600         Py_BEGIN_ALLOW_THREADS
601         plugin_log(LOG_ERR, "%s", text);
602         Py_END_ALLOW_THREADS
603         Py_RETURN_NONE;
604 }
605
606 static PyObject *cpy_warning(PyObject *self, PyObject *args) {
607         const char *text;
608         if (PyArg_ParseTuple(args, "et", NULL, &text) == 0) return NULL;
609         Py_BEGIN_ALLOW_THREADS
610         plugin_log(LOG_WARNING, "%s", text);
611         Py_END_ALLOW_THREADS
612         Py_RETURN_NONE;
613 }
614
615 static PyObject *cpy_notice(PyObject *self, PyObject *args) {
616         const char *text;
617         if (PyArg_ParseTuple(args, "et", NULL, &text) == 0) return NULL;
618         Py_BEGIN_ALLOW_THREADS
619         plugin_log(LOG_NOTICE, "%s", text);
620         Py_END_ALLOW_THREADS
621         Py_RETURN_NONE;
622 }
623
624 static PyObject *cpy_info(PyObject *self, PyObject *args) {
625         const char *text;
626         if (PyArg_ParseTuple(args, "et", NULL, &text) == 0) return NULL;
627         Py_BEGIN_ALLOW_THREADS
628         plugin_log(LOG_INFO, "%s", text);
629         Py_END_ALLOW_THREADS
630         Py_RETURN_NONE;
631 }
632
633 static PyObject *cpy_debug(PyObject *self, PyObject *args) {
634 #ifdef COLLECT_DEBUG
635         const char *text;
636         if (PyArg_ParseTuple(args, "et", NULL, &text) == 0) return NULL;
637         Py_BEGIN_ALLOW_THREADS
638         plugin_log(LOG_DEBUG, "%s", text);
639         Py_END_ALLOW_THREADS
640 #endif
641         Py_RETURN_NONE;
642 }
643
644 static PyObject *cpy_unregister_generic(cpy_callback_t **list_head, PyObject *arg, const char *desc) {
645         char buf[512];
646         const char *name;
647         cpy_callback_t *prev = NULL, *tmp;
648
649         Py_INCREF(arg);
650         name = cpy_unicode_or_bytes_to_string(&arg);
651         if (name == NULL) {
652                 PyErr_Clear();
653                 if (!PyCallable_Check(arg)) {
654                         PyErr_SetString(PyExc_TypeError, "This function needs a string or a callable object as its only parameter.");
655                         Py_DECREF(arg);
656                         return NULL;
657                 }
658                 cpy_build_name(buf, sizeof(buf), arg, NULL);
659                 name = buf;
660         }
661         for (tmp = *list_head; tmp; prev = tmp, tmp = tmp->next)
662                 if (strcmp(name, tmp->name) == 0)
663                         break;
664         
665         Py_DECREF(arg);
666         if (tmp == NULL) {
667                 PyErr_Format(PyExc_RuntimeError, "Unable to unregister %s callback '%s'.", desc, name);
668                 return NULL;
669         }
670         /* Yes, this is actually save. To call this function the caller has to
671          * hold the GIL. Well, save as long as there is only one GIL anyway ... */
672         if (prev == NULL)
673                 *list_head = tmp->next;
674         else
675                 prev->next = tmp->next;
676         cpy_destroy_user_data(tmp);
677         Py_RETURN_NONE;
678 }
679
680 typedef int cpy_unregister_function_t(const char *name);
681
682 static PyObject *cpy_unregister_generic_userdata(cpy_unregister_function_t *unreg, PyObject *arg, const char *desc) {
683         char buf[512];
684         const char *name;
685
686         Py_INCREF(arg);
687         name = cpy_unicode_or_bytes_to_string(&arg);
688         if (name == NULL) {
689                 PyErr_Clear();
690                 if (!PyCallable_Check(arg)) {
691                         PyErr_SetString(PyExc_TypeError, "This function needs a string or a callable object as its only parameter.");
692                         Py_DECREF(&arg);
693                         return NULL;
694                 }
695                 cpy_build_name(buf, sizeof(buf), arg, NULL);
696                 name = buf;
697         }
698         if (unreg(name) == 0) {
699                 Py_DECREF(&arg);
700                 Py_RETURN_NONE;
701         }
702         PyErr_Format(PyExc_RuntimeError, "Unable to unregister %s callback '%s'.", desc, name);
703         Py_DECREF(&arg);
704         return NULL;
705 }
706
707 static PyObject *cpy_unregister_log(PyObject *self, PyObject *arg) {
708         return cpy_unregister_generic_userdata(plugin_unregister_log, arg, "log");
709 }
710
711 static PyObject *cpy_unregister_init(PyObject *self, PyObject *arg) {
712         return cpy_unregister_generic(&cpy_init_callbacks, arg, "init");
713 }
714
715 static PyObject *cpy_unregister_config(PyObject *self, PyObject *arg) {
716         return cpy_unregister_generic(&cpy_config_callbacks, arg, "config");
717 }
718
719 static PyObject *cpy_unregister_read(PyObject *self, PyObject *arg) {
720         return cpy_unregister_generic_userdata(plugin_unregister_read, arg, "read");
721 }
722
723 static PyObject *cpy_unregister_write(PyObject *self, PyObject *arg) {
724         return cpy_unregister_generic_userdata(plugin_unregister_write, arg, "write");
725 }
726
727 static PyObject *cpy_unregister_notification(PyObject *self, PyObject *arg) {
728         return cpy_unregister_generic_userdata(plugin_unregister_notification, arg, "notification");
729 }
730
731 static PyObject *cpy_unregister_flush(PyObject *self, PyObject *arg) {
732         return cpy_unregister_generic_userdata(plugin_unregister_flush, arg, "flush");
733 }
734
735 static PyObject *cpy_unregister_shutdown(PyObject *self, PyObject *arg) {
736         return cpy_unregister_generic(&cpy_shutdown_callbacks, arg, "shutdown");
737 }
738
739 static PyMethodDef cpy_methods[] = {
740         {"debug", cpy_debug, METH_VARARGS, log_doc},
741         {"info", cpy_info, METH_VARARGS, log_doc},
742         {"notice", cpy_notice, METH_VARARGS, log_doc},
743         {"warning", cpy_warning, METH_VARARGS, log_doc},
744         {"error", cpy_error, METH_VARARGS, log_doc},
745         {"flush", (PyCFunction) cpy_flush, METH_VARARGS | METH_KEYWORDS, flush_doc},
746         {"register_log", (PyCFunction) cpy_register_log, METH_VARARGS | METH_KEYWORDS, reg_log_doc},
747         {"register_init", (PyCFunction) cpy_register_init, METH_VARARGS | METH_KEYWORDS, reg_init_doc},
748         {"register_config", (PyCFunction) cpy_register_config, METH_VARARGS | METH_KEYWORDS, reg_config_doc},
749         {"register_read", (PyCFunction) cpy_register_read, METH_VARARGS | METH_KEYWORDS, reg_read_doc},
750         {"register_write", (PyCFunction) cpy_register_write, METH_VARARGS | METH_KEYWORDS, reg_write_doc},
751         {"register_notification", (PyCFunction) cpy_register_notification, METH_VARARGS | METH_KEYWORDS, reg_notification_doc},
752         {"register_flush", (PyCFunction) cpy_register_flush, METH_VARARGS | METH_KEYWORDS, reg_flush_doc},
753         {"register_shutdown", (PyCFunction) cpy_register_shutdown, METH_VARARGS | METH_KEYWORDS, reg_shutdown_doc},
754         {"unregister_log", cpy_unregister_log, METH_O, unregister_doc},
755         {"unregister_init", cpy_unregister_init, METH_O, unregister_doc},
756         {"unregister_config", cpy_unregister_config, METH_O, unregister_doc},
757         {"unregister_read", cpy_unregister_read, METH_O, unregister_doc},
758         {"unregister_write", cpy_unregister_write, METH_O, unregister_doc},
759         {"unregister_notification", cpy_unregister_notification, METH_O, unregister_doc},
760         {"unregister_flush", cpy_unregister_flush, METH_O, unregister_doc},
761         {"unregister_shutdown", cpy_unregister_shutdown, METH_O, unregister_doc},
762         {0, 0, 0, 0}
763 };
764
765 static int cpy_shutdown(void) {
766         cpy_callback_t *c;
767         PyObject *ret;
768         
769         /* This can happen if the module was loaded but not configured. */
770         if (state != NULL)
771                 PyEval_RestoreThread(state);
772
773         for (c = cpy_shutdown_callbacks; c; c = c->next) {
774                 ret = PyObject_CallFunctionObjArgs(c->callback, c->data, (void *) 0); /* New reference. */
775                 if (ret == NULL)
776                         cpy_log_exception("shutdown callback");
777                 else
778                         Py_DECREF(ret);
779         }
780         PyErr_Print();
781         Py_Finalize();
782         return 0;
783 }
784
785 static void cpy_int_handler(int sig) {
786         return;
787 }
788
789 static void *cpy_interactive(void *data) {
790         sigset_t sigset;
791         struct sigaction sig_int_action, old;
792         
793         /* Signal handler in a plugin? Bad stuff, but the best way to
794          * handle it I guess. In an interactive session people will
795          * press Ctrl+C at some time, which will generate a SIGINT.
796          * This will cause collectd to shutdown, thus killing the
797          * interactive interpreter, and leaving the terminal in a
798          * mess. Chances are, this isn't what the user wanted to do.
799          * 
800          * So this is the plan:
801          * 1. Block SIGINT in the main thread.
802          * 2. Install our own signal handler that does nothing.
803          * 3. Unblock SIGINT in the interactive thread.
804          *
805          * This will make sure that SIGINT won't kill collectd but
806          * still interrupt syscalls like sleep and pause.
807          * It does not raise a KeyboardInterrupt exception because so
808          * far nobody managed to figure out how to do that. */
809         memset (&sig_int_action, '\0', sizeof (sig_int_action));
810         sig_int_action.sa_handler = cpy_int_handler;
811         sigaction (SIGINT, &sig_int_action, &old);
812         
813         sigemptyset(&sigset);
814         sigaddset(&sigset, SIGINT);
815         pthread_sigmask(SIG_UNBLOCK, &sigset, NULL);
816         PyEval_AcquireThread(state);
817         if (PyImport_ImportModule("readline") == NULL) {
818                 /* This interactive session will suck. */
819                 cpy_log_exception("interactive session init");
820         }
821         PyRun_InteractiveLoop(stdin, "<stdin>");
822         PyErr_Print();
823         PyEval_ReleaseThread(state);
824         NOTICE("python: Interactive interpreter exited, stopping collectd ...");
825         /* Restore the original collectd SIGINT handler and raise SIGINT.
826          * The main thread still has SIGINT blocked and there's nothing we
827          * can do about that so this thread will handle it. But that's not
828          * important, except that it won't interrupt the main loop and so
829          * it might take a few seconds before collectd really shuts down. */
830         sigaction (SIGINT, &old, NULL);
831         raise(SIGINT);
832         pause();
833         return NULL;
834 }
835
836 static int cpy_init(void) {
837         cpy_callback_t *c;
838         PyObject *ret;
839         static pthread_t thread;
840         sigset_t sigset;
841         
842         PyEval_InitThreads();
843         /* Now it's finally OK to use python threads. */
844         for (c = cpy_init_callbacks; c; c = c->next) {
845                 ret = PyObject_CallFunctionObjArgs(c->callback, c->data, (void *) 0); /* New reference. */
846                 if (ret == NULL)
847                         cpy_log_exception("init callback");
848                 else
849                         Py_DECREF(ret);
850         }
851         sigemptyset(&sigset);
852         sigaddset(&sigset, SIGINT);
853         pthread_sigmask(SIG_BLOCK, &sigset, NULL);
854         state = PyEval_SaveThread();
855         if (do_interactive) {
856                 if (pthread_create(&thread, NULL, cpy_interactive, NULL)) {
857                         ERROR("python: Error creating thread for interactive interpreter.");
858                 }
859         }
860
861         return 0;
862 }
863
864 static PyObject *cpy_oconfig_to_pyconfig(oconfig_item_t *ci, PyObject *parent) {
865         int i;
866         PyObject *item, *values, *children, *tmp;
867         
868         if (parent == NULL)
869                 parent = Py_None;
870         
871         values = PyTuple_New(ci->values_num); /* New reference. */
872         for (i = 0; i < ci->values_num; ++i) {
873                 if (ci->values[i].type == OCONFIG_TYPE_STRING) {
874                         PyTuple_SET_ITEM(values, i, cpy_string_to_unicode_or_bytes(ci->values[i].value.string));
875                 } else if (ci->values[i].type == OCONFIG_TYPE_NUMBER) {
876                         PyTuple_SET_ITEM(values, i, PyFloat_FromDouble(ci->values[i].value.number));
877                 } else if (ci->values[i].type == OCONFIG_TYPE_BOOLEAN) {
878                         PyTuple_SET_ITEM(values, i, PyBool_FromLong(ci->values[i].value.boolean));
879                 }
880         }
881         
882         item = PyObject_CallFunction((void *) &ConfigType, "sONO", ci->key, parent, values, Py_None);
883         if (item == NULL)
884                 return NULL;
885         children = PyTuple_New(ci->children_num); /* New reference. */
886         for (i = 0; i < ci->children_num; ++i) {
887                 PyTuple_SET_ITEM(children, i, cpy_oconfig_to_pyconfig(ci->children + i, item));
888         }
889         tmp = ((Config *) item)->children;
890         ((Config *) item)->children = children;
891         Py_XDECREF(tmp);
892         return item;
893 }
894
895 static struct PyModuleDef collectdmodule = {
896         PyModuleDef_HEAD_INIT,
897         "collectd",   /* name of module */
898         "Where does this go?", /* module documentation, may be NULL */
899         -1,
900         cpy_methods
901 };
902
903 PyMODINIT_FUNC PyInit_collectd(void) {
904         return PyModule_Create(&collectdmodule);
905 }
906
907 static int cpy_config(oconfig_item_t *ci) {
908         int i;
909         PyObject *sys, *tb;
910         PyObject *sys_path;
911         PyObject *module;
912         
913         /* Ok in theory we shouldn't do initialization at this point
914          * but we have to. In order to give python scripts a chance
915          * to register a config callback we need to be able to execute
916          * python code during the config callback so we have to start
917          * the interpreter here. */
918         /* Do *not* use the python "thread" module at this point! */
919
920 #ifdef IS_PY3K
921         /* Add a builtin module, before Py_Initialize */
922         PyImport_AppendInittab("collectd", PyInit_collectd);
923 #endif
924         
925         Py_Initialize();
926         
927         PyType_Ready(&ConfigType);
928         PyType_Ready(&PluginDataType);
929         ValuesType.tp_base = &PluginDataType;
930         PyType_Ready(&ValuesType);
931         NotificationType.tp_base = &PluginDataType;
932         PyType_Ready(&NotificationType);
933         sys = PyImport_ImportModule("sys"); /* New reference. */
934         if (sys == NULL) {
935                 cpy_log_exception("python initialization");
936                 return 1;
937         }
938         sys_path = PyObject_GetAttrString(sys, "path"); /* New reference. */
939         Py_DECREF(sys);
940         if (sys_path == NULL) {
941                 cpy_log_exception("python initialization");
942                 return 1;
943         }
944 #ifdef IS_PY3K
945         module = PyImport_ImportModule("collectd");
946 #else
947         module = Py_InitModule("collectd", cpy_methods); /* Borrowed reference. */
948 #endif
949         PyModule_AddObject(module, "Config", (void *) &ConfigType); /* Steals a reference. */
950         PyModule_AddObject(module, "Values", (void *) &ValuesType); /* Steals a reference. */
951         PyModule_AddObject(module, "Notification", (void *) &NotificationType); /* Steals a reference. */
952         PyModule_AddIntConstant(module, "LOG_DEBUG", LOG_DEBUG);
953         PyModule_AddIntConstant(module, "LOG_INFO", LOG_INFO);
954         PyModule_AddIntConstant(module, "LOG_NOTICE", LOG_NOTICE);
955         PyModule_AddIntConstant(module, "LOG_WARNING", LOG_WARNING);
956         PyModule_AddIntConstant(module, "LOG_ERROR", LOG_ERR);
957         PyModule_AddIntConstant(module, "NOTIF_FAILURE", NOTIF_FAILURE);
958         PyModule_AddIntConstant(module, "NOTIF_WARNING", NOTIF_WARNING);
959         PyModule_AddIntConstant(module, "NOTIF_OKAY", NOTIF_OKAY);
960         for (i = 0; i < ci->children_num; ++i) {
961                 oconfig_item_t *item = ci->children + i;
962                 
963                 if (strcasecmp(item->key, "Interactive") == 0) {
964                         if (item->values_num != 1 || item->values[0].type != OCONFIG_TYPE_BOOLEAN)
965                                 continue;
966                         do_interactive = item->values[0].value.boolean;
967                 } else if (strcasecmp(item->key, "Encoding") == 0) {
968                         if (item->values_num != 1 || item->values[0].type != OCONFIG_TYPE_STRING)
969                                 continue;
970                         /* Why is this even necessary? And undocumented? */
971                         if (PyUnicode_SetDefaultEncoding(item->values[0].value.string))
972                                 cpy_log_exception("setting default encoding");
973                 } else if (strcasecmp(item->key, "LogTraces") == 0) {
974                         if (item->values_num != 1 || item->values[0].type != OCONFIG_TYPE_BOOLEAN)
975                                 continue;
976                         if (!item->values[0].value.boolean) {
977                                 Py_XDECREF(cpy_format_exception);
978                                 cpy_format_exception = NULL;
979                                 continue;
980                         }
981                         if (cpy_format_exception)
982                                 continue;
983                         tb = PyImport_ImportModule("traceback"); /* New reference. */
984                         if (tb == NULL) {
985                                 cpy_log_exception("python initialization");
986                                 continue;
987                         }
988                         cpy_format_exception = PyObject_GetAttrString(tb, "format_exception"); /* New reference. */
989                         Py_DECREF(tb);
990                         if (cpy_format_exception == NULL)
991                                 cpy_log_exception("python initialization");
992                 } else if (strcasecmp(item->key, "ModulePath") == 0) {
993                         char *dir = NULL;
994                         PyObject *dir_object;
995                         
996                         if (cf_util_get_string(item, &dir) != 0) 
997                                 continue;
998                         dir_object = cpy_string_to_unicode_or_bytes(dir); /* New reference. */
999                         if (dir_object == NULL) {
1000                                 ERROR("python plugin: Unable to convert \"%s\" to "
1001                                       "a python object.", dir);
1002                                 free(dir);
1003                                 cpy_log_exception("python initialization");
1004                                 continue;
1005                         }
1006                         if (PyList_Append(sys_path, dir_object) != 0) {
1007                                 ERROR("python plugin: Unable to append \"%s\" to "
1008                                       "python module path.", dir);
1009                                 cpy_log_exception("python initialization");
1010                         }
1011                         Py_DECREF(dir_object);
1012                         free(dir);
1013                 } else if (strcasecmp(item->key, "Import") == 0) {
1014                         char *module_name = NULL;
1015                         PyObject *module;
1016                         
1017                         if (cf_util_get_string(item, &module_name) != 0) 
1018                                 continue;
1019                         module = PyImport_ImportModule(module_name); /* New reference. */
1020                         if (module == NULL) {
1021                                 ERROR("python plugin: Error importing module \"%s\".", module_name);
1022                                 cpy_log_exception("importing module");
1023                         }
1024                         free(module_name);
1025                         Py_XDECREF(module);
1026                 } else if (strcasecmp(item->key, "Module") == 0) {
1027                         char *name = NULL;
1028                         cpy_callback_t *c;
1029                         PyObject *ret;
1030                         
1031                         if (cf_util_get_string(item, &name) != 0)
1032                                 continue;
1033                         for (c = cpy_config_callbacks; c; c = c->next) {
1034                                 if (strcasecmp(c->name + 7, name) == 0)
1035                                         break;
1036                         }
1037                         if (c == NULL) {
1038                                 WARNING("python plugin: Found a configuration for the \"%s\" plugin, "
1039                                         "but the plugin isn't loaded or didn't register "
1040                                         "a configuration callback.", name);
1041                                 free(name);
1042                                 continue;
1043                         }
1044                         free(name);
1045                         if (c->data == NULL)
1046                                 ret = PyObject_CallFunction(c->callback, "N",
1047                                         cpy_oconfig_to_pyconfig(item, NULL)); /* New reference. */
1048                         else
1049                                 ret = PyObject_CallFunction(c->callback, "NO",
1050                                         cpy_oconfig_to_pyconfig(item, NULL), c->data); /* New reference. */
1051                         if (ret == NULL)
1052                                 cpy_log_exception("loading module");
1053                         else
1054                                 Py_DECREF(ret);
1055                 } else {
1056                         WARNING("python plugin: Ignoring unknown config key \"%s\".", item->key);
1057                 }
1058         }
1059         Py_DECREF(sys_path);
1060         return 0;
1061 }
1062
1063 void module_register(void) {
1064         plugin_register_complex_config("python", cpy_config);
1065         plugin_register_init("python", cpy_init);
1066         plugin_register_shutdown("python", cpy_shutdown);
1067 }