Auto-Merge pull request #2948 from rubenk/turbostat-free-the-right-vars
[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
32 #include "collectd.h"
33
34 #include "common.h"
35
36 #include "cpython.h"
37
38 typedef struct cpy_callback_s {
39   char *name;
40   PyObject *callback;
41   PyObject *data;
42   struct cpy_callback_s *next;
43 } cpy_callback_t;
44
45 static char log_doc[] = "This function sends a string to all logging plugins.";
46
47 static char get_ds_doc[] =
48     "get_dataset(name) -> definition\n"
49     "\n"
50     "Returns the definition of a dataset specified by name.\n"
51     "\n"
52     "'name' is a string specifying the dataset to query.\n"
53     "'definition' is a list of 4-tuples. Every tuple represents a \n"
54     "    data source within the data set and its 4 values are the \n"
55     "    name, type, min and max value.\n"
56     "    'name' is a string.\n"
57     "    'type' is a string that is equal to either DS_TYPE_COUNTER,\n"
58     "        DS_TYPE_GAUGE, DS_TYPE_DERIVE or DS_TYPE_ABSOLUTE.\n"
59     "    'min' and 'max' are either a float or None.";
60
61 static char flush_doc[] = "flush([plugin][, timeout][, identifier]) -> None\n"
62                           "\n"
63                           "Flushes the cache of another plugin.";
64
65 static char unregister_doc[] =
66     "Unregisters a callback. This function needs exactly one parameter either\n"
67     "the function to unregister or the callback identifier to unregister.";
68
69 static char reg_log_doc[] =
70     "register_log(callback[, data][, name]) -> identifier\n"
71     "\n"
72     "Register a callback function for log messages.\n"
73     "\n"
74     "'callback' is a callable object that will be called every time something\n"
75     "    is logged.\n"
76     "'data' is an optional object that will be passed back to the callback\n"
77     "    function every time it is called.\n"
78     "'name' is an optional identifier for this callback. The default name\n"
79     "    is 'python.<module>'.\n"
80     "    Every callback needs a unique identifier, so if you want to\n"
81     "    register this callback multiple time from the same module you need\n"
82     "    to specify a name here.\n"
83     "'identifier' is the full identifier assigned to this callback.\n"
84     "\n"
85     "The callback function will be called with two or three parameters:\n"
86     "severity: An integer that should be compared to the LOG_ constants.\n"
87     "message: The text to be logged.\n"
88     "data: The optional data parameter passed to the register function.\n"
89     "    If the parameter was omitted it will be omitted here, too.";
90
91 static char reg_init_doc[] =
92     "register_init(callback[, data][, name]) -> identifier\n"
93     "\n"
94     "Register a callback function that will be executed once after the "
95     "config.\n"
96     "file has been read, all plugins heve been loaded and the collectd has\n"
97     "forked into the background.\n"
98     "\n"
99     "'callback' is a callable object that will be executed.\n"
100     "'data' is an optional object that will be passed back to the callback\n"
101     "    function when 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 without parameters, except for\n"
110     "data if it was supplied.";
111
112 static char reg_config_doc[] =
113     "register_config(callback[, data][, name]) -> identifier\n"
114     "\n"
115     "Register a callback function for config file entries.\n"
116     "'callback' is a callable object that will be called for every config "
117     "block.\n"
118     "'data' is an optional object that will be passed back to the callback\n"
119     "    function every time it is called.\n"
120     "'name' is an optional identifier for this callback. The default name\n"
121     "    is 'python.<module>'.\n"
122     "    Every callback needs a unique identifier, so if you want to\n"
123     "    register this callback multiple time from the same module you need\n"
124     "    to specify a name here.\n"
125     "'identifier' is the full identifier assigned to this callback.\n"
126     "\n"
127     "The callback function will be called with one or two parameters:\n"
128     "config: A Config object.\n"
129     "data: The optional data parameter passed to the register function.\n"
130     "    If the parameter was omitted it will be omitted here, too.";
131
132 static char reg_read_doc[] =
133     "register_read(callback[, interval][, data][, name]) -> identifier\n"
134     "\n"
135     "Register a callback function for reading data. It will just be called\n"
136     "in a fixed interval to signal that it's time to dispatch new values.\n"
137     "'callback' is a callable object that will be called every time something\n"
138     "    is logged.\n"
139     "'interval' is the number of seconds between between calls to the "
140     "callback\n"
141     "    function. Full float precision is supported here.\n"
142     "'data' is an optional object that will be passed back to the callback\n"
143     "    function every time it is called.\n"
144     "'name' is an optional identifier for this callback. The default name\n"
145     "    is 'python.<module>'.\n"
146     "    Every callback needs a unique identifier, so if you want to\n"
147     "    register this callback multiple time from the same module you need\n"
148     "    to specify a name here.\n"
149     "'identifier' is the full identifier assigned to this callback.\n"
150     "\n"
151     "The callback function will be called without parameters, except for\n"
152     "data if it was supplied.";
153
154 static char reg_write_doc[] =
155     "register_write(callback[, data][, name]) -> identifier\n"
156     "\n"
157     "Register a callback function to receive values dispatched by other "
158     "plugins.\n"
159     "'callback' is a callable object that will be called every time a value\n"
160     "    is dispatched.\n"
161     "'data' is an optional object that will be passed back to the callback\n"
162     "    function every time it is called.\n"
163     "'name' is an optional identifier for this callback. The default name\n"
164     "    is 'python.<module>'.\n"
165     "    Every callback needs a unique identifier, so if you want to\n"
166     "    register this callback multiple time from the same module you need\n"
167     "    to specify a name here.\n"
168     "'identifier' is the full identifier assigned to this callback.\n"
169     "\n"
170     "The callback function will be called with one or two parameters:\n"
171     "values: A Values object which is a copy of the dispatched values.\n"
172     "data: The optional data parameter passed to the register function.\n"
173     "    If the parameter was omitted it will be omitted here, too.";
174
175 static char reg_notification_doc[] =
176     "register_notification(callback[, data][, name]) -> identifier\n"
177     "\n"
178     "Register a callback function for notifications.\n"
179     "'callback' is a callable object that will be called every time a "
180     "notification\n"
181     "    is dispatched.\n"
182     "'data' is an optional object that will be passed back to the callback\n"
183     "    function every time it is called.\n"
184     "'name' is an optional identifier for this callback. The default name\n"
185     "    is 'python.<module>'.\n"
186     "    Every callback needs a unique identifier, so if you want to\n"
187     "    register this callback multiple time from the same module you need\n"
188     "    to specify a name here.\n"
189     "'identifier' is the full identifier assigned to this callback.\n"
190     "\n"
191     "The callback function will be called with one or two parameters:\n"
192     "notification: A copy of the notification that was dispatched.\n"
193     "data: The optional data parameter passed to the register function.\n"
194     "    If the parameter was omitted it will be omitted here, too.";
195
196 static char reg_flush_doc[] =
197     "register_flush(callback[, data][, name]) -> identifier\n"
198     "\n"
199     "Register a callback function for flush messages.\n"
200     "'callback' is a callable object that will be called every time a plugin\n"
201     "    requests a flush for either this or all plugins.\n"
202     "'data' is an optional object that will be passed back to the callback\n"
203     "    function every time it is called.\n"
204     "'name' is an optional identifier for this callback. The default name\n"
205     "    is 'python.<module>'.\n"
206     "    Every callback needs a unique identifier, so if you want to\n"
207     "    register this callback multiple time from the same module you need\n"
208     "    to specify a name here.\n"
209     "'identifier' is the full identifier assigned to this callback.\n"
210     "\n"
211     "The callback function will be called with two or three parameters:\n"
212     "timeout: Indicates that only data older than 'timeout' seconds is to\n"
213     "    be flushed.\n"
214     "id: Specifies which values are to be flushed. Might be None.\n"
215     "data: The optional data parameter passed to the register function.\n"
216     "    If the parameter was omitted it will be omitted here, too.";
217
218 static char reg_shutdown_doc[] =
219     "register_shutdown(callback[, data][, name]) -> identifier\n"
220     "\n"
221     "Register a callback function for collectd shutdown.\n"
222     "'callback' is a callable object that will be called once collectd is\n"
223     "    shutting down.\n"
224     "'data' is an optional object that will be passed back to the callback\n"
225     "    function if it is called.\n"
226     "'name' is an optional identifier for this callback. The default name\n"
227     "    is 'python.<module>'.\n"
228     "    Every callback needs a unique identifier, so if you want to\n"
229     "    register this callback multiple time from the same module you need\n"
230     "    to specify a name here.\n"
231     "'identifier' is the full identifier assigned to this callback.\n"
232     "\n"
233     "The callback function will be called with no parameters except for\n"
234     "    data if it was supplied.";
235
236 static char CollectdError_doc[] =
237     "Basic exception for collectd Python scripts.\n"
238     "\n"
239     "Throwing this exception will not cause a stacktrace to be logged, \n"
240     "even if LogTraces is enabled in the config.";
241
242 static pthread_t main_thread;
243 static PyOS_sighandler_t python_sigint_handler;
244 static _Bool do_interactive = 0;
245
246 /* This is our global thread state. Python saves some stuff in thread-local
247  * storage. So if we allow the interpreter to run in the background
248  * (the scriptwriters might have created some threads from python), we have
249  * to save the state so we can resume it later after shutdown. */
250
251 static PyThreadState *state;
252
253 static PyObject *sys_path, *cpy_format_exception, *CollectdError;
254
255 static cpy_callback_t *cpy_config_callbacks;
256 static cpy_callback_t *cpy_init_callbacks;
257 static cpy_callback_t *cpy_shutdown_callbacks;
258
259 /* Make sure to hold the GIL while modifying these. */
260 static int cpy_shutdown_triggered = 0;
261 static int cpy_num_callbacks = 0;
262
263 static void cpy_destroy_user_data(void *data) {
264   cpy_callback_t *c = data;
265   free(c->name);
266   CPY_LOCK_THREADS
267   Py_DECREF(c->callback);
268   Py_XDECREF(c->data);
269   free(c);
270   --cpy_num_callbacks;
271   if (!cpy_num_callbacks && cpy_shutdown_triggered) {
272     Py_Finalize();
273     return;
274   }
275   CPY_RELEASE_THREADS
276 }
277
278 /* You must hold the GIL to call this function!
279  * But if you managed to extract the callback parameter then you probably
280  * already do. */
281
282 static void cpy_build_name(char *buf, size_t size, PyObject *callback,
283                            const char *name) {
284   const char *module = NULL;
285   PyObject *mod = NULL;
286
287   if (name != NULL) {
288     snprintf(buf, size, "python.%s", name);
289     return;
290   }
291
292   mod = PyObject_GetAttrString(callback, "__module__"); /* New reference. */
293   if (mod != NULL)
294     module = cpy_unicode_or_bytes_to_string(&mod);
295
296   if (module != NULL) {
297     snprintf(buf, size, "python.%s", module);
298     Py_XDECREF(mod);
299     PyErr_Clear();
300     return;
301   }
302   Py_XDECREF(mod);
303
304   snprintf(buf, size, "python.%p", callback);
305   PyErr_Clear();
306 }
307
308 void cpy_log_exception(const char *context) {
309   int l = 0, collectd_error;
310   const char *typename = NULL, *message = NULL;
311   PyObject *type, *value, *traceback, *tn, *m, *list;
312
313   PyErr_Fetch(&type, &value, &traceback);
314   PyErr_NormalizeException(&type, &value, &traceback);
315   if (type == NULL)
316     return;
317   collectd_error = PyErr_GivenExceptionMatches(value, CollectdError);
318   tn = PyObject_GetAttrString(type, "__name__"); /* New reference. */
319   m = PyObject_Str(value);                       /* New reference. */
320   if (tn != NULL)
321     typename = cpy_unicode_or_bytes_to_string(&tn);
322   if (m != NULL)
323     message = cpy_unicode_or_bytes_to_string(&m);
324   if (typename == NULL)
325     typename = "NamelessException";
326   if (message == NULL)
327     message = "N/A";
328   Py_BEGIN_ALLOW_THREADS;
329   if (collectd_error) {
330     WARNING("%s in %s: %s", typename, context, message);
331   } else {
332     ERROR("Unhandled python exception in %s: %s: %s", context, typename,
333           message);
334   }
335   Py_END_ALLOW_THREADS;
336   Py_XDECREF(tn);
337   Py_XDECREF(m);
338   if (!cpy_format_exception || !traceback || collectd_error) {
339     PyErr_Clear();
340     Py_DECREF(type);
341     Py_XDECREF(value);
342     Py_XDECREF(traceback);
343     return;
344   }
345   list = PyObject_CallFunction(cpy_format_exception, "NNN", type, value,
346                                traceback); /* New reference. Steals references
347                                               from "type", "value" and
348                                               "traceback". */
349   if (list)
350     l = PyObject_Length(list);
351
352   for (int i = 0; i < l; ++i) {
353     PyObject *line;
354     char const *msg;
355     char *cpy;
356
357     line = PyList_GET_ITEM(list, i); /* Borrowed reference. */
358     Py_INCREF(line);
359
360     msg = cpy_unicode_or_bytes_to_string(&line);
361     Py_DECREF(line);
362     if (msg == NULL)
363       continue;
364
365     cpy = strdup(msg);
366     if (cpy == NULL)
367       continue;
368
369     if (cpy[strlen(cpy) - 1] == '\n')
370       cpy[strlen(cpy) - 1] = 0;
371
372     Py_BEGIN_ALLOW_THREADS;
373     ERROR("%s", cpy);
374     Py_END_ALLOW_THREADS;
375
376     free(cpy);
377   }
378
379   Py_XDECREF(list);
380   PyErr_Clear();
381 }
382
383 static int cpy_read_callback(user_data_t *data) {
384   cpy_callback_t *c = data->data;
385   PyObject *ret;
386
387   CPY_LOCK_THREADS
388   ret = PyObject_CallFunctionObjArgs(c->callback, c->data,
389                                      (void *)0); /* New reference. */
390   if (ret == NULL) {
391     cpy_log_exception("read callback");
392   } else {
393     Py_DECREF(ret);
394   }
395   CPY_RELEASE_THREADS
396   if (ret == NULL)
397     return 1;
398   return 0;
399 }
400
401 static int cpy_write_callback(const data_set_t *ds,
402                               const value_list_t *value_list,
403                               user_data_t *data) {
404   cpy_callback_t *c = data->data;
405   PyObject *ret, *list, *temp, *dict = NULL;
406   Values *v;
407
408   CPY_LOCK_THREADS
409   list = PyList_New(value_list->values_len); /* New reference. */
410   if (list == NULL) {
411     cpy_log_exception("write callback");
412     CPY_RETURN_FROM_THREADS 0;
413   }
414   for (size_t i = 0; i < value_list->values_len; ++i) {
415     if (ds->ds[i].type == DS_TYPE_COUNTER) {
416       PyList_SetItem(
417           list, i, PyLong_FromUnsignedLongLong(value_list->values[i].counter));
418     } else if (ds->ds[i].type == DS_TYPE_GAUGE) {
419       PyList_SetItem(list, i, PyFloat_FromDouble(value_list->values[i].gauge));
420     } else if (ds->ds[i].type == DS_TYPE_DERIVE) {
421       PyList_SetItem(list, i,
422                      PyLong_FromLongLong(value_list->values[i].derive));
423     } else if (ds->ds[i].type == DS_TYPE_ABSOLUTE) {
424       PyList_SetItem(
425           list, i, PyLong_FromUnsignedLongLong(value_list->values[i].absolute));
426     } else {
427       Py_BEGIN_ALLOW_THREADS;
428       ERROR("cpy_write_callback: Unknown value type %d.", ds->ds[i].type);
429       Py_END_ALLOW_THREADS;
430       Py_DECREF(list);
431       CPY_RETURN_FROM_THREADS 0;
432     }
433     if (PyErr_Occurred() != NULL) {
434       cpy_log_exception("value building for write callback");
435       Py_DECREF(list);
436       CPY_RETURN_FROM_THREADS 0;
437     }
438   }
439   dict = PyDict_New(); /* New reference. */
440   if (value_list->meta) {
441     char **table = NULL;
442     meta_data_t *meta = value_list->meta;
443
444     int num = meta_data_toc(meta, &table);
445     for (int i = 0; i < num; ++i) {
446       int type;
447       char *string;
448       int64_t si;
449       uint64_t ui;
450       double d;
451       _Bool b;
452
453       type = meta_data_type(meta, table[i]);
454       if (type == MD_TYPE_STRING) {
455         if (meta_data_get_string(meta, table[i], &string))
456           continue;
457         temp = cpy_string_to_unicode_or_bytes(string); /* New reference. */
458         free(string);
459         PyDict_SetItemString(dict, table[i], temp);
460         Py_XDECREF(temp);
461       } else if (type == MD_TYPE_SIGNED_INT) {
462         if (meta_data_get_signed_int(meta, table[i], &si))
463           continue;
464         PyObject *sival = PyLong_FromLongLong(si); /* New reference */
465         temp = PyObject_CallFunctionObjArgs((void *)&SignedType, sival,
466                                             (void *)0); /* New reference. */
467         PyDict_SetItemString(dict, table[i], temp);
468         Py_XDECREF(temp);
469         Py_XDECREF(sival);
470       } else if (type == MD_TYPE_UNSIGNED_INT) {
471         if (meta_data_get_unsigned_int(meta, table[i], &ui))
472           continue;
473         PyObject *uval = PyLong_FromUnsignedLongLong(ui); /* New reference */
474         temp = PyObject_CallFunctionObjArgs((void *)&UnsignedType, uval,
475                                             (void *)0); /* New reference. */
476         PyDict_SetItemString(dict, table[i], temp);
477         Py_XDECREF(temp);
478         Py_XDECREF(uval);
479       } else if (type == MD_TYPE_DOUBLE) {
480         if (meta_data_get_double(meta, table[i], &d))
481           continue;
482         temp = PyFloat_FromDouble(d); /* New reference. */
483         PyDict_SetItemString(dict, table[i], temp);
484         Py_XDECREF(temp);
485       } else if (type == MD_TYPE_BOOLEAN) {
486         if (meta_data_get_boolean(meta, table[i], &b))
487           continue;
488         if (b)
489           PyDict_SetItemString(dict, table[i], Py_True);
490         else
491           PyDict_SetItemString(dict, table[i], Py_False);
492       }
493       free(table[i]);
494     }
495     free(table);
496   }
497   v = (Values *)Values_New(); /* New reference. */
498   sstrncpy(v->data.host, value_list->host, sizeof(v->data.host));
499   sstrncpy(v->data.type, value_list->type, sizeof(v->data.type));
500   sstrncpy(v->data.type_instance, value_list->type_instance,
501            sizeof(v->data.type_instance));
502   sstrncpy(v->data.plugin, value_list->plugin, sizeof(v->data.plugin));
503   sstrncpy(v->data.plugin_instance, value_list->plugin_instance,
504            sizeof(v->data.plugin_instance));
505   v->data.time = CDTIME_T_TO_DOUBLE(value_list->time);
506   v->interval = CDTIME_T_TO_DOUBLE(value_list->interval);
507   Py_CLEAR(v->values);
508   v->values = list;
509   Py_CLEAR(v->meta);
510   v->meta = dict; /* Steals a reference. */
511   ret = PyObject_CallFunctionObjArgs(c->callback, v, c->data,
512                                      (void *)0); /* New reference. */
513   Py_XDECREF(v);
514   if (ret == NULL) {
515     cpy_log_exception("write callback");
516   } else {
517     Py_DECREF(ret);
518   }
519   CPY_RELEASE_THREADS
520   return 0;
521 }
522
523 static int cpy_notification_callback(const notification_t *notification,
524                                      user_data_t *data) {
525   cpy_callback_t *c = data->data;
526   PyObject *ret, *notify;
527   Notification *n;
528
529   CPY_LOCK_THREADS
530   PyObject *dict = PyDict_New(); /* New reference. */
531   for (notification_meta_t *meta = notification->meta; meta != NULL;
532        meta = meta->next) {
533     PyObject *temp = NULL;
534     if (meta->type == NM_TYPE_STRING) {
535       temp = cpy_string_to_unicode_or_bytes(
536           meta->nm_value.nm_string); /* New reference. */
537       PyDict_SetItemString(dict, meta->name, temp);
538       Py_XDECREF(temp);
539     } else if (meta->type == NM_TYPE_SIGNED_INT) {
540       PyObject *sival = PyLong_FromLongLong(meta->nm_value.nm_signed_int);
541       temp = PyObject_CallFunctionObjArgs((void *)&SignedType, sival,
542                                           (void *)0); /* New reference. */
543       PyDict_SetItemString(dict, meta->name, temp);
544       Py_XDECREF(temp);
545       Py_XDECREF(sival);
546     } else if (meta->type == NM_TYPE_UNSIGNED_INT) {
547       PyObject *uval =
548           PyLong_FromUnsignedLongLong(meta->nm_value.nm_unsigned_int);
549       temp = PyObject_CallFunctionObjArgs((void *)&UnsignedType, uval,
550                                           (void *)0); /* New reference. */
551       PyDict_SetItemString(dict, meta->name, temp);
552       Py_XDECREF(temp);
553       Py_XDECREF(uval);
554     } else if (meta->type == NM_TYPE_DOUBLE) {
555       temp = PyFloat_FromDouble(meta->nm_value.nm_double); /* New reference. */
556       PyDict_SetItemString(dict, meta->name, temp);
557       Py_XDECREF(temp);
558     } else if (meta->type == NM_TYPE_BOOLEAN) {
559       PyDict_SetItemString(dict, meta->name,
560                            meta->nm_value.nm_boolean ? Py_True : Py_False);
561     }
562   }
563   notify = Notification_New(); /* New reference. */
564   n = (Notification *)notify;
565   sstrncpy(n->data.host, notification->host, sizeof(n->data.host));
566   sstrncpy(n->data.type, notification->type, sizeof(n->data.type));
567   sstrncpy(n->data.type_instance, notification->type_instance,
568            sizeof(n->data.type_instance));
569   sstrncpy(n->data.plugin, notification->plugin, sizeof(n->data.plugin));
570   sstrncpy(n->data.plugin_instance, notification->plugin_instance,
571            sizeof(n->data.plugin_instance));
572   n->data.time = CDTIME_T_TO_DOUBLE(notification->time);
573   sstrncpy(n->message, notification->message, sizeof(n->message));
574   n->severity = notification->severity;
575   Py_CLEAR(n->meta);
576   n->meta = dict; /* Steals a reference. */
577   ret = PyObject_CallFunctionObjArgs(c->callback, n, c->data,
578                                      (void *)0); /* New reference. */
579   Py_XDECREF(notify);
580   if (ret == NULL) {
581     cpy_log_exception("notification callback");
582   } else {
583     Py_DECREF(ret);
584   }
585   CPY_RELEASE_THREADS
586   return 0;
587 }
588
589 static void cpy_log_callback(int severity, const char *message,
590                              user_data_t *data) {
591   cpy_callback_t *c = data->data;
592   PyObject *ret, *text;
593
594   CPY_LOCK_THREADS
595   text = cpy_string_to_unicode_or_bytes(message); /* New reference. */
596   if (c->data == NULL)
597     ret = PyObject_CallFunction(
598         c->callback, "iN", severity,
599         text); /* New reference. Steals a reference from "text". */
600   else
601     ret = PyObject_CallFunction(
602         c->callback, "iNO", severity, text,
603         c->data); /* New reference. Steals a reference from "text". */
604
605   if (ret == NULL) {
606     /* FIXME */
607     /* Do we really want to trigger a log callback because a log callback
608      * failed?
609      * Probably not. */
610     PyErr_Print();
611     /* In case someone wanted to be clever, replaced stderr and failed at that.
612      */
613     PyErr_Clear();
614   } else {
615     Py_DECREF(ret);
616   }
617   CPY_RELEASE_THREADS
618 }
619
620 static void cpy_flush_callback(int timeout, const char *id, user_data_t *data) {
621   cpy_callback_t *c = data->data;
622   PyObject *ret, *text;
623
624   CPY_LOCK_THREADS
625   if (id) {
626     text = cpy_string_to_unicode_or_bytes(id);
627   } else {
628     text = Py_None;
629     Py_INCREF(text);
630   }
631   if (c->data == NULL)
632     ret = PyObject_CallFunction(c->callback, "iN", timeout,
633                                 text); /* New reference. */
634   else
635     ret = PyObject_CallFunction(c->callback, "iNO", timeout, text,
636                                 c->data); /* New reference. */
637
638   if (ret == NULL) {
639     cpy_log_exception("flush callback");
640   } else {
641     Py_DECREF(ret);
642   }
643   CPY_RELEASE_THREADS
644 }
645
646 static PyObject *cpy_register_generic(cpy_callback_t **list_head,
647                                       PyObject *args, PyObject *kwds) {
648   char buf[512];
649   cpy_callback_t *c;
650   char *name = NULL;
651   PyObject *callback = NULL, *data = NULL, *mod = NULL;
652   static char *kwlist[] = {"callback", "data", "name", NULL};
653
654   if (PyArg_ParseTupleAndKeywords(args, kwds, "O|Oet", kwlist, &callback, &data,
655                                   NULL, &name) == 0)
656     return NULL;
657   if (PyCallable_Check(callback) == 0) {
658     PyMem_Free(name);
659     PyErr_SetString(PyExc_TypeError, "callback needs a be a callable object.");
660     return NULL;
661   }
662   cpy_build_name(buf, sizeof(buf), callback, name);
663
664   Py_INCREF(callback);
665   Py_XINCREF(data);
666
667   c = calloc(1, sizeof(*c));
668   if (c == NULL)
669     return NULL;
670
671   c->name = strdup(buf);
672   c->callback = callback;
673   c->data = data;
674   c->next = *list_head;
675   ++cpy_num_callbacks;
676   *list_head = c;
677   Py_XDECREF(mod);
678   PyMem_Free(name);
679   return cpy_string_to_unicode_or_bytes(buf);
680 }
681
682 static PyObject *float_or_none(float number) {
683   if (isnan(number)) {
684     Py_RETURN_NONE;
685   }
686   return PyFloat_FromDouble(number);
687 }
688
689 static PyObject *cpy_get_dataset(PyObject *self, PyObject *args) {
690   char *name;
691   const data_set_t *ds;
692   PyObject *list, *tuple;
693
694   if (PyArg_ParseTuple(args, "et", NULL, &name) == 0)
695     return NULL;
696   ds = plugin_get_ds(name);
697   PyMem_Free(name);
698   if (ds == NULL) {
699     PyErr_Format(PyExc_TypeError, "Dataset %s not found", name);
700     return NULL;
701   }
702   list = PyList_New(ds->ds_num); /* New reference. */
703   for (size_t i = 0; i < ds->ds_num; ++i) {
704     tuple = PyTuple_New(4);
705     PyTuple_SET_ITEM(tuple, 0, cpy_string_to_unicode_or_bytes(ds->ds[i].name));
706     PyTuple_SET_ITEM(
707         tuple, 1,
708         cpy_string_to_unicode_or_bytes(DS_TYPE_TO_STRING(ds->ds[i].type)));
709     PyTuple_SET_ITEM(tuple, 2, float_or_none(ds->ds[i].min));
710     PyTuple_SET_ITEM(tuple, 3, float_or_none(ds->ds[i].max));
711     PyList_SET_ITEM(list, i, tuple);
712   }
713   return list;
714 }
715
716 static PyObject *cpy_flush(PyObject *self, PyObject *args, PyObject *kwds) {
717   int timeout = -1;
718   char *plugin = NULL, *identifier = NULL;
719   static char *kwlist[] = {"plugin", "timeout", "identifier", NULL};
720
721   if (PyArg_ParseTupleAndKeywords(args, kwds, "|etiet", kwlist, NULL, &plugin,
722                                   &timeout, NULL, &identifier) == 0)
723     return NULL;
724   Py_BEGIN_ALLOW_THREADS;
725   plugin_flush(plugin, timeout, identifier);
726   Py_END_ALLOW_THREADS;
727   PyMem_Free(plugin);
728   PyMem_Free(identifier);
729   Py_RETURN_NONE;
730 }
731
732 static PyObject *cpy_register_config(PyObject *self, PyObject *args,
733                                      PyObject *kwds) {
734   return cpy_register_generic(&cpy_config_callbacks, args, kwds);
735 }
736
737 static PyObject *cpy_register_init(PyObject *self, PyObject *args,
738                                    PyObject *kwds) {
739   return cpy_register_generic(&cpy_init_callbacks, args, kwds);
740 }
741
742 typedef int reg_function_t(const char *name, void *callback, void *data);
743
744 static PyObject *cpy_register_generic_userdata(void *reg, void *handler,
745                                                PyObject *args, PyObject *kwds) {
746   char buf[512];
747   reg_function_t *register_function = (reg_function_t *)reg;
748   cpy_callback_t *c = NULL;
749   char *name = NULL;
750   PyObject *callback = NULL, *data = NULL;
751   static char *kwlist[] = {"callback", "data", "name", NULL};
752
753   if (PyArg_ParseTupleAndKeywords(args, kwds, "O|Oet", kwlist, &callback, &data,
754                                   NULL, &name) == 0)
755     return NULL;
756   if (PyCallable_Check(callback) == 0) {
757     PyMem_Free(name);
758     PyErr_SetString(PyExc_TypeError, "callback needs a be a callable object.");
759     return NULL;
760   }
761   cpy_build_name(buf, sizeof(buf), callback, name);
762   PyMem_Free(name);
763
764   Py_INCREF(callback);
765   Py_XINCREF(data);
766
767   c = calloc(1, sizeof(*c));
768   if (c == NULL)
769     return NULL;
770
771   c->name = strdup(buf);
772   c->callback = callback;
773   c->data = data;
774   c->next = NULL;
775
776   register_function(buf, handler,
777                     &(user_data_t){
778                         .data = c,
779                         .free_func = cpy_destroy_user_data,
780                     });
781
782   ++cpy_num_callbacks;
783   return cpy_string_to_unicode_or_bytes(buf);
784 }
785
786 static PyObject *cpy_register_read(PyObject *self, PyObject *args,
787                                    PyObject *kwds) {
788   char buf[512];
789   cpy_callback_t *c = NULL;
790   double interval = 0;
791   char *name = NULL;
792   PyObject *callback = NULL, *data = NULL;
793   static char *kwlist[] = {"callback", "interval", "data", "name", NULL};
794
795   if (PyArg_ParseTupleAndKeywords(args, kwds, "O|dOet", kwlist, &callback,
796                                   &interval, &data, NULL, &name) == 0)
797     return NULL;
798   if (PyCallable_Check(callback) == 0) {
799     PyMem_Free(name);
800     PyErr_SetString(PyExc_TypeError, "callback needs a be a callable object.");
801     return NULL;
802   }
803   cpy_build_name(buf, sizeof(buf), callback, name);
804   PyMem_Free(name);
805
806   Py_INCREF(callback);
807   Py_XINCREF(data);
808
809   c = calloc(1, sizeof(*c));
810   if (c == NULL)
811     return NULL;
812
813   c->name = strdup(buf);
814   c->callback = callback;
815   c->data = data;
816   c->next = NULL;
817
818   plugin_register_complex_read(
819       /* group = */ "python", buf, cpy_read_callback,
820       DOUBLE_TO_CDTIME_T(interval),
821       &(user_data_t){
822           .data = c,
823           .free_func = cpy_destroy_user_data,
824       });
825   ++cpy_num_callbacks;
826   return cpy_string_to_unicode_or_bytes(buf);
827 }
828
829 static PyObject *cpy_register_log(PyObject *self, PyObject *args,
830                                   PyObject *kwds) {
831   return cpy_register_generic_userdata((void *)plugin_register_log,
832                                        (void *)cpy_log_callback, args, kwds);
833 }
834
835 static PyObject *cpy_register_write(PyObject *self, PyObject *args,
836                                     PyObject *kwds) {
837   return cpy_register_generic_userdata((void *)plugin_register_write,
838                                        (void *)cpy_write_callback, args, kwds);
839 }
840
841 static PyObject *cpy_register_notification(PyObject *self, PyObject *args,
842                                            PyObject *kwds) {
843   return cpy_register_generic_userdata((void *)plugin_register_notification,
844                                        (void *)cpy_notification_callback, args,
845                                        kwds);
846 }
847
848 static PyObject *cpy_register_flush(PyObject *self, PyObject *args,
849                                     PyObject *kwds) {
850   return cpy_register_generic_userdata((void *)plugin_register_flush,
851                                        (void *)cpy_flush_callback, args, kwds);
852 }
853
854 static PyObject *cpy_register_shutdown(PyObject *self, PyObject *args,
855                                        PyObject *kwds) {
856   return cpy_register_generic(&cpy_shutdown_callbacks, args, kwds);
857 }
858
859 static PyObject *cpy_error(PyObject *self, PyObject *args) {
860   char *text;
861   if (PyArg_ParseTuple(args, "et", NULL, &text) == 0)
862     return NULL;
863   Py_BEGIN_ALLOW_THREADS;
864   plugin_log(LOG_ERR, "%s", text);
865   Py_END_ALLOW_THREADS;
866   PyMem_Free(text);
867   Py_RETURN_NONE;
868 }
869
870 static PyObject *cpy_warning(PyObject *self, PyObject *args) {
871   char *text;
872   if (PyArg_ParseTuple(args, "et", NULL, &text) == 0)
873     return NULL;
874   Py_BEGIN_ALLOW_THREADS;
875   plugin_log(LOG_WARNING, "%s", text);
876   Py_END_ALLOW_THREADS;
877   PyMem_Free(text);
878   Py_RETURN_NONE;
879 }
880
881 static PyObject *cpy_notice(PyObject *self, PyObject *args) {
882   char *text;
883   if (PyArg_ParseTuple(args, "et", NULL, &text) == 0)
884     return NULL;
885   Py_BEGIN_ALLOW_THREADS;
886   plugin_log(LOG_NOTICE, "%s", text);
887   Py_END_ALLOW_THREADS;
888   PyMem_Free(text);
889   Py_RETURN_NONE;
890 }
891
892 static PyObject *cpy_info(PyObject *self, PyObject *args) {
893   char *text;
894   if (PyArg_ParseTuple(args, "et", NULL, &text) == 0)
895     return NULL;
896   Py_BEGIN_ALLOW_THREADS;
897   plugin_log(LOG_INFO, "%s", text);
898   Py_END_ALLOW_THREADS;
899   PyMem_Free(text);
900   Py_RETURN_NONE;
901 }
902
903 static PyObject *cpy_debug(PyObject *self, PyObject *args) {
904 #ifdef COLLECT_DEBUG
905   char *text;
906   if (PyArg_ParseTuple(args, "et", NULL, &text) == 0)
907     return NULL;
908   Py_BEGIN_ALLOW_THREADS;
909   plugin_log(LOG_DEBUG, "%s", text);
910   Py_END_ALLOW_THREADS;
911   PyMem_Free(text);
912 #endif
913   Py_RETURN_NONE;
914 }
915
916 static PyObject *cpy_unregister_generic(cpy_callback_t **list_head,
917                                         PyObject *arg, const char *desc) {
918   char buf[512];
919   const char *name;
920   cpy_callback_t *prev = NULL, *tmp;
921
922   Py_INCREF(arg);
923   name = cpy_unicode_or_bytes_to_string(&arg);
924   if (name == NULL) {
925     PyErr_Clear();
926     if (!PyCallable_Check(arg)) {
927       PyErr_SetString(PyExc_TypeError, "This function needs a string or a "
928                                        "callable object as its only "
929                                        "parameter.");
930       Py_DECREF(arg);
931       return NULL;
932     }
933     cpy_build_name(buf, sizeof(buf), arg, NULL);
934     name = buf;
935   }
936   for (tmp = *list_head; tmp; prev = tmp, tmp = tmp->next)
937     if (strcmp(name, tmp->name) == 0)
938       break;
939
940   Py_DECREF(arg);
941   if (tmp == NULL) {
942     PyErr_Format(PyExc_RuntimeError, "Unable to unregister %s callback '%s'.",
943                  desc, name);
944     return NULL;
945   }
946   /* Yes, this is actually safe. To call this function the caller has to
947    * hold the GIL. Well, safe as long as there is only one GIL anyway ... */
948   if (prev == NULL)
949     *list_head = tmp->next;
950   else
951     prev->next = tmp->next;
952   cpy_destroy_user_data(tmp);
953   Py_RETURN_NONE;
954 }
955
956 static void cpy_unregister_list(cpy_callback_t **list_head) {
957   cpy_callback_t *cur, *next;
958   for (cur = *list_head; cur; cur = next) {
959     next = cur->next;
960     cpy_destroy_user_data(cur);
961   }
962   *list_head = NULL;
963 }
964
965 typedef int cpy_unregister_function_t(const char *name);
966
967 static PyObject *
968 cpy_unregister_generic_userdata(cpy_unregister_function_t *unreg, PyObject *arg,
969                                 const char *desc) {
970   char buf[512];
971   const char *name;
972
973   Py_INCREF(arg);
974   name = cpy_unicode_or_bytes_to_string(&arg);
975   if (name == NULL) {
976     PyErr_Clear();
977     if (!PyCallable_Check(arg)) {
978       PyErr_SetString(PyExc_TypeError, "This function needs a string or a "
979                                        "callable object as its only "
980                                        "parameter.");
981       Py_DECREF(arg);
982       return NULL;
983     }
984     cpy_build_name(buf, sizeof(buf), arg, NULL);
985     name = buf;
986   }
987   if (unreg(name) == 0) {
988     Py_DECREF(arg);
989     Py_RETURN_NONE;
990   }
991   PyErr_Format(PyExc_RuntimeError, "Unable to unregister %s callback '%s'.",
992                desc, name);
993   Py_DECREF(arg);
994   return NULL;
995 }
996
997 static PyObject *cpy_unregister_log(PyObject *self, PyObject *arg) {
998   return cpy_unregister_generic_userdata(plugin_unregister_log, arg, "log");
999 }
1000
1001 static PyObject *cpy_unregister_init(PyObject *self, PyObject *arg) {
1002   return cpy_unregister_generic(&cpy_init_callbacks, arg, "init");
1003 }
1004
1005 static PyObject *cpy_unregister_config(PyObject *self, PyObject *arg) {
1006   return cpy_unregister_generic(&cpy_config_callbacks, arg, "config");
1007 }
1008
1009 static PyObject *cpy_unregister_read(PyObject *self, PyObject *arg) {
1010   return cpy_unregister_generic_userdata(plugin_unregister_read, arg, "read");
1011 }
1012
1013 static PyObject *cpy_unregister_write(PyObject *self, PyObject *arg) {
1014   return cpy_unregister_generic_userdata(plugin_unregister_write, arg, "write");
1015 }
1016
1017 static PyObject *cpy_unregister_notification(PyObject *self, PyObject *arg) {
1018   return cpy_unregister_generic_userdata(plugin_unregister_notification, arg,
1019                                          "notification");
1020 }
1021
1022 static PyObject *cpy_unregister_flush(PyObject *self, PyObject *arg) {
1023   return cpy_unregister_generic_userdata(plugin_unregister_flush, arg, "flush");
1024 }
1025
1026 static PyObject *cpy_unregister_shutdown(PyObject *self, PyObject *arg) {
1027   return cpy_unregister_generic(&cpy_shutdown_callbacks, arg, "shutdown");
1028 }
1029
1030 static PyMethodDef cpy_methods[] = {
1031     {"debug", cpy_debug, METH_VARARGS, log_doc},
1032     {"info", cpy_info, METH_VARARGS, log_doc},
1033     {"notice", cpy_notice, METH_VARARGS, log_doc},
1034     {"warning", cpy_warning, METH_VARARGS, log_doc},
1035     {"error", cpy_error, METH_VARARGS, log_doc},
1036     {"get_dataset", (PyCFunction)cpy_get_dataset, METH_VARARGS, get_ds_doc},
1037     {"flush", (PyCFunction)cpy_flush, METH_VARARGS | METH_KEYWORDS, flush_doc},
1038     {"register_log", (PyCFunction)cpy_register_log,
1039      METH_VARARGS | METH_KEYWORDS, reg_log_doc},
1040     {"register_init", (PyCFunction)cpy_register_init,
1041      METH_VARARGS | METH_KEYWORDS, reg_init_doc},
1042     {"register_config", (PyCFunction)cpy_register_config,
1043      METH_VARARGS | METH_KEYWORDS, reg_config_doc},
1044     {"register_read", (PyCFunction)cpy_register_read,
1045      METH_VARARGS | METH_KEYWORDS, reg_read_doc},
1046     {"register_write", (PyCFunction)cpy_register_write,
1047      METH_VARARGS | METH_KEYWORDS, reg_write_doc},
1048     {"register_notification", (PyCFunction)cpy_register_notification,
1049      METH_VARARGS | METH_KEYWORDS, reg_notification_doc},
1050     {"register_flush", (PyCFunction)cpy_register_flush,
1051      METH_VARARGS | METH_KEYWORDS, reg_flush_doc},
1052     {"register_shutdown", (PyCFunction)cpy_register_shutdown,
1053      METH_VARARGS | METH_KEYWORDS, reg_shutdown_doc},
1054     {"unregister_log", cpy_unregister_log, METH_O, unregister_doc},
1055     {"unregister_init", cpy_unregister_init, METH_O, unregister_doc},
1056     {"unregister_config", cpy_unregister_config, METH_O, unregister_doc},
1057     {"unregister_read", cpy_unregister_read, METH_O, unregister_doc},
1058     {"unregister_write", cpy_unregister_write, METH_O, unregister_doc},
1059     {"unregister_notification", cpy_unregister_notification, METH_O,
1060      unregister_doc},
1061     {"unregister_flush", cpy_unregister_flush, METH_O, unregister_doc},
1062     {"unregister_shutdown", cpy_unregister_shutdown, METH_O, unregister_doc},
1063     {0, 0, 0, 0}};
1064
1065 static int cpy_shutdown(void) {
1066   PyObject *ret;
1067
1068   if (!state) {
1069     printf(
1070         "================================================================\n");
1071     printf(
1072         "collectd shutdown while running an interactive session. This will\n");
1073     printf("probably leave your terminal in a mess.\n");
1074     printf("Run the command \"reset\" to get it back into a usable state.\n");
1075     printf("You can press Ctrl+D in the interactive session to\n");
1076     printf("close collectd and avoid this problem in the future.\n");
1077     printf(
1078         "================================================================\n");
1079   }
1080
1081   CPY_LOCK_THREADS
1082
1083   for (cpy_callback_t *c = cpy_shutdown_callbacks; c; c = c->next) {
1084     ret = PyObject_CallFunctionObjArgs(c->callback, c->data,
1085                                        (void *)0); /* New reference. */
1086     if (ret == NULL)
1087       cpy_log_exception("shutdown callback");
1088     else
1089       Py_DECREF(ret);
1090   }
1091   PyErr_Print();
1092
1093   Py_BEGIN_ALLOW_THREADS;
1094   cpy_unregister_list(&cpy_config_callbacks);
1095   cpy_unregister_list(&cpy_init_callbacks);
1096   cpy_unregister_list(&cpy_shutdown_callbacks);
1097   cpy_shutdown_triggered = 1;
1098   Py_END_ALLOW_THREADS;
1099
1100   if (!cpy_num_callbacks) {
1101     Py_Finalize();
1102     return 0;
1103   }
1104
1105   CPY_RELEASE_THREADS
1106   return 0;
1107 }
1108
1109 static void *cpy_interactive(void *pipefd) {
1110   PyOS_sighandler_t cur_sig;
1111
1112   /* Signal handler in a plugin? Bad stuff, but the best way to
1113    * handle it I guess. In an interactive session people will
1114    * press Ctrl+C at some time, which will generate a SIGINT.
1115    * This will cause collectd to shutdown, thus killing the
1116    * interactive interpreter, and leaving the terminal in a
1117    * mess. Chances are, this isn't what the user wanted to do.
1118    *
1119    * So this is the plan:
1120    * 1. Restore Python's own signal handler
1121    * 2. Tell Python we just forked so it will accept this thread
1122    *    as the main one. No version of Python will ever handle
1123    *    interrupts anywhere but in the main thread.
1124    * 3. After the interactive loop is done, restore collectd's
1125    *    SIGINT handler.
1126    * 4. Raise SIGINT for a clean shutdown. The signal is sent to
1127    *    the main thread to ensure it wakes up the main interval
1128    *    sleep so that collectd shuts down immediately not in 10
1129    *    seconds.
1130    *
1131    * This will make sure that SIGINT won't kill collectd but
1132    * still interrupt syscalls like sleep and pause. */
1133
1134   if (PyImport_ImportModule("readline") == NULL) {
1135     /* This interactive session will suck. */
1136     cpy_log_exception("interactive session init");
1137   }
1138   cur_sig = PyOS_setsig(SIGINT, python_sigint_handler);
1139   PyOS_AfterFork();
1140   PyEval_InitThreads();
1141   close(*(int *)pipefd);
1142   PyRun_InteractiveLoop(stdin, "<stdin>");
1143   PyOS_setsig(SIGINT, cur_sig);
1144   PyErr_Print();
1145   state = PyEval_SaveThread();
1146   NOTICE("python: Interactive interpreter exited, stopping collectd ...");
1147   pthread_kill(main_thread, SIGINT);
1148   return NULL;
1149 }
1150
1151 static int cpy_init(void) {
1152   PyObject *ret;
1153   int pipefd[2];
1154   char buf;
1155   static pthread_t thread;
1156
1157   if (!Py_IsInitialized()) {
1158     WARNING("python: Plugin loaded but not configured.");
1159     plugin_unregister_shutdown("python");
1160     Py_Finalize();
1161     return 0;
1162   }
1163   main_thread = pthread_self();
1164   if (do_interactive) {
1165     if (pipe(pipefd)) {
1166       ERROR("python: Unable to create pipe.");
1167       return 1;
1168     }
1169     if (plugin_thread_create(&thread, NULL, cpy_interactive, pipefd + 1,
1170                              "python interpreter")) {
1171       ERROR("python: Error creating thread for interactive interpreter.");
1172     }
1173     if (read(pipefd[0], &buf, 1))
1174       ;
1175     (void)close(pipefd[0]);
1176   } else {
1177     PyEval_InitThreads();
1178     state = PyEval_SaveThread();
1179   }
1180   CPY_LOCK_THREADS
1181   for (cpy_callback_t *c = cpy_init_callbacks; c; c = c->next) {
1182     ret = PyObject_CallFunctionObjArgs(c->callback, c->data,
1183                                        (void *)0); /* New reference. */
1184     if (ret == NULL)
1185       cpy_log_exception("init callback");
1186     else
1187       Py_DECREF(ret);
1188   }
1189   CPY_RELEASE_THREADS
1190
1191   return 0;
1192 }
1193
1194 static PyObject *cpy_oconfig_to_pyconfig(oconfig_item_t *ci, PyObject *parent) {
1195   PyObject *item, *values, *children, *tmp;
1196
1197   if (parent == NULL)
1198     parent = Py_None;
1199
1200   values = PyTuple_New(ci->values_num); /* New reference. */
1201   for (int i = 0; i < ci->values_num; ++i) {
1202     if (ci->values[i].type == OCONFIG_TYPE_STRING) {
1203       PyTuple_SET_ITEM(
1204           values, i,
1205           cpy_string_to_unicode_or_bytes(ci->values[i].value.string));
1206     } else if (ci->values[i].type == OCONFIG_TYPE_NUMBER) {
1207       PyTuple_SET_ITEM(values, i,
1208                        PyFloat_FromDouble(ci->values[i].value.number));
1209     } else if (ci->values[i].type == OCONFIG_TYPE_BOOLEAN) {
1210       PyTuple_SET_ITEM(values, i, PyBool_FromLong(ci->values[i].value.boolean));
1211     }
1212   }
1213
1214   tmp = cpy_string_to_unicode_or_bytes(ci->key);
1215   item = PyObject_CallFunction((void *)&ConfigType, "NONO", tmp, parent, values,
1216                                Py_None);
1217   if (item == NULL)
1218     return NULL;
1219   children = PyTuple_New(ci->children_num); /* New reference. */
1220   for (int i = 0; i < ci->children_num; ++i) {
1221     PyTuple_SET_ITEM(children, i,
1222                      cpy_oconfig_to_pyconfig(ci->children + i, item));
1223   }
1224   tmp = ((Config *)item)->children;
1225   ((Config *)item)->children = children;
1226   Py_XDECREF(tmp);
1227   return item;
1228 }
1229
1230 #ifdef IS_PY3K
1231 static struct PyModuleDef collectdmodule = {
1232     PyModuleDef_HEAD_INIT, "collectd",  /* name of module */
1233     "The python interface to collectd", /* module documentation, may be NULL */
1234     -1, cpy_methods};
1235
1236 PyMODINIT_FUNC PyInit_collectd(void) {
1237   return PyModule_Create(&collectdmodule);
1238 }
1239 #endif
1240
1241 static int cpy_init_python(void) {
1242   PyOS_sighandler_t cur_sig;
1243   PyObject *sys, *errordict;
1244   PyObject *module;
1245
1246 #ifdef IS_PY3K
1247   wchar_t *argv = L"";
1248   /* Add a builtin module, before Py_Initialize */
1249   PyImport_AppendInittab("collectd", PyInit_collectd);
1250 #else
1251   char *argv = "";
1252 #endif
1253
1254   /* Chances are the current signal handler is already SIG_DFL, but let's make
1255    * sure. */
1256   cur_sig = PyOS_setsig(SIGINT, SIG_DFL);
1257   Py_Initialize();
1258   python_sigint_handler = PyOS_setsig(SIGINT, cur_sig);
1259
1260   PyType_Ready(&ConfigType);
1261   PyType_Ready(&PluginDataType);
1262   ValuesType.tp_base = &PluginDataType;
1263   PyType_Ready(&ValuesType);
1264   NotificationType.tp_base = &PluginDataType;
1265   PyType_Ready(&NotificationType);
1266   SignedType.tp_base = &PyLong_Type;
1267   PyType_Ready(&SignedType);
1268   UnsignedType.tp_base = &PyLong_Type;
1269   PyType_Ready(&UnsignedType);
1270   errordict = PyDict_New();
1271   PyDict_SetItemString(
1272       errordict, "__doc__",
1273       cpy_string_to_unicode_or_bytes(CollectdError_doc)); /* New reference. */
1274   CollectdError = PyErr_NewException("collectd.CollectdError", NULL, errordict);
1275   sys = PyImport_ImportModule("sys"); /* New reference. */
1276   if (sys == NULL) {
1277     cpy_log_exception("python initialization");
1278     return 1;
1279   }
1280   sys_path = PyObject_GetAttrString(sys, "path"); /* New reference. */
1281   Py_DECREF(sys);
1282   if (sys_path == NULL) {
1283     cpy_log_exception("python initialization");
1284     return 1;
1285   }
1286   PySys_SetArgv(1, &argv);
1287   PyList_SetSlice(sys_path, 0, 1, NULL);
1288
1289 #ifdef IS_PY3K
1290   module = PyImport_ImportModule("collectd");
1291 #else
1292   module = Py_InitModule("collectd", cpy_methods); /* Borrowed reference. */
1293 #endif
1294   PyModule_AddObject(module, "Config",
1295                      (void *)&ConfigType); /* Steals a reference. */
1296   PyModule_AddObject(module, "Values",
1297                      (void *)&ValuesType); /* Steals a reference. */
1298   PyModule_AddObject(module, "Notification",
1299                      (void *)&NotificationType); /* Steals a reference. */
1300   PyModule_AddObject(module, "Signed",
1301                      (void *)&SignedType); /* Steals a reference. */
1302   PyModule_AddObject(module, "Unsigned",
1303                      (void *)&UnsignedType); /* Steals a reference. */
1304   Py_XINCREF(CollectdError);
1305   PyModule_AddObject(module, "CollectdError",
1306                      CollectdError); /* Steals a reference. */
1307   PyModule_AddIntConstant(module, "LOG_DEBUG", LOG_DEBUG);
1308   PyModule_AddIntConstant(module, "LOG_INFO", LOG_INFO);
1309   PyModule_AddIntConstant(module, "LOG_NOTICE", LOG_NOTICE);
1310   PyModule_AddIntConstant(module, "LOG_WARNING", LOG_WARNING);
1311   PyModule_AddIntConstant(module, "LOG_ERROR", LOG_ERR);
1312   PyModule_AddIntConstant(module, "NOTIF_FAILURE", NOTIF_FAILURE);
1313   PyModule_AddIntConstant(module, "NOTIF_WARNING", NOTIF_WARNING);
1314   PyModule_AddIntConstant(module, "NOTIF_OKAY", NOTIF_OKAY);
1315   PyModule_AddStringConstant(module, "DS_TYPE_COUNTER",
1316                              DS_TYPE_TO_STRING(DS_TYPE_COUNTER));
1317   PyModule_AddStringConstant(module, "DS_TYPE_GAUGE",
1318                              DS_TYPE_TO_STRING(DS_TYPE_GAUGE));
1319   PyModule_AddStringConstant(module, "DS_TYPE_DERIVE",
1320                              DS_TYPE_TO_STRING(DS_TYPE_DERIVE));
1321   PyModule_AddStringConstant(module, "DS_TYPE_ABSOLUTE",
1322                              DS_TYPE_TO_STRING(DS_TYPE_ABSOLUTE));
1323   return 0;
1324 }
1325
1326 static int cpy_config(oconfig_item_t *ci) {
1327   PyObject *tb;
1328   int status = 0;
1329
1330   /* Ok in theory we shouldn't do initialization at this point
1331    * but we have to. In order to give python scripts a chance
1332    * to register a config callback we need to be able to execute
1333    * python code during the config callback so we have to start
1334    * the interpreter here. */
1335   /* Do *not* use the python "thread" module at this point! */
1336
1337   if (!Py_IsInitialized() && cpy_init_python())
1338     return 1;
1339
1340   for (int i = 0; i < ci->children_num; ++i) {
1341     oconfig_item_t *item = ci->children + i;
1342
1343     if (strcasecmp(item->key, "Interactive") == 0) {
1344       if (cf_util_get_boolean(item, &do_interactive) != 0) {
1345         status = 1;
1346         continue;
1347       }
1348     } else if (strcasecmp(item->key, "Encoding") == 0) {
1349       char *encoding = NULL;
1350       if (cf_util_get_string(item, &encoding) != 0) {
1351         status = 1;
1352         continue;
1353       }
1354 #ifdef IS_PY3K
1355       ERROR("python: \"Encoding\" was used in the config file but Python3 was "
1356             "used, which does not support changing encodings");
1357       status = 1;
1358       sfree(encoding);
1359       continue;
1360 #else
1361       /* Why is this even necessary? And undocumented? */
1362       if (PyUnicode_SetDefaultEncoding(encoding)) {
1363         cpy_log_exception("setting default encoding");
1364         status = 1;
1365       }
1366 #endif
1367       sfree(encoding);
1368     } else if (strcasecmp(item->key, "LogTraces") == 0) {
1369       _Bool log_traces;
1370       if (cf_util_get_boolean(item, &log_traces) != 0) {
1371         status = 1;
1372         continue;
1373       }
1374       if (!log_traces) {
1375         Py_XDECREF(cpy_format_exception);
1376         cpy_format_exception = NULL;
1377         continue;
1378       }
1379       if (cpy_format_exception)
1380         continue;
1381       tb = PyImport_ImportModule("traceback"); /* New reference. */
1382       if (tb == NULL) {
1383         cpy_log_exception("python initialization");
1384         status = 1;
1385         continue;
1386       }
1387       cpy_format_exception =
1388           PyObject_GetAttrString(tb, "format_exception"); /* New reference. */
1389       Py_DECREF(tb);
1390       if (cpy_format_exception == NULL) {
1391         cpy_log_exception("python initialization");
1392         status = 1;
1393       }
1394     } else if (strcasecmp(item->key, "ModulePath") == 0) {
1395       char *dir = NULL;
1396       PyObject *dir_object;
1397
1398       if (cf_util_get_string(item, &dir) != 0) {
1399         status = 1;
1400         continue;
1401       }
1402       dir_object = cpy_string_to_unicode_or_bytes(dir); /* New reference. */
1403       if (dir_object == NULL) {
1404         ERROR("python plugin: Unable to convert \"%s\" to "
1405               "a python object.",
1406               dir);
1407         free(dir);
1408         cpy_log_exception("python initialization");
1409         status = 1;
1410         continue;
1411       }
1412       if (PyList_Insert(sys_path, 0, dir_object) != 0) {
1413         ERROR("python plugin: Unable to prepend \"%s\" to "
1414               "python module path.",
1415               dir);
1416         cpy_log_exception("python initialization");
1417         status = 1;
1418       }
1419       Py_DECREF(dir_object);
1420       free(dir);
1421     } else if (strcasecmp(item->key, "Import") == 0) {
1422       char *module_name = NULL;
1423       PyObject *module;
1424
1425       if (cf_util_get_string(item, &module_name) != 0) {
1426         status = 1;
1427         continue;
1428       }
1429       module = PyImport_ImportModule(module_name); /* New reference. */
1430       if (module == NULL) {
1431         ERROR("python plugin: Error importing module \"%s\".", module_name);
1432         cpy_log_exception("importing module");
1433         status = 1;
1434       }
1435       free(module_name);
1436       Py_XDECREF(module);
1437     } else if (strcasecmp(item->key, "Module") == 0) {
1438       char *name = NULL;
1439       cpy_callback_t *c;
1440       PyObject *ret;
1441
1442       if (cf_util_get_string(item, &name) != 0) {
1443         status = 1;
1444         continue;
1445       }
1446       for (c = cpy_config_callbacks; c; c = c->next) {
1447         if (strcasecmp(c->name + 7, name) == 0)
1448           break;
1449       }
1450       if (c == NULL) {
1451         WARNING("python plugin: Found a configuration for the \"%s\" plugin, "
1452                 "but the plugin isn't loaded or didn't register "
1453                 "a configuration callback.",
1454                 name);
1455         free(name);
1456         continue;
1457       }
1458       free(name);
1459       if (c->data == NULL)
1460         ret = PyObject_CallFunction(
1461             c->callback, "N",
1462             cpy_oconfig_to_pyconfig(item, NULL)); /* New reference. */
1463       else
1464         ret = PyObject_CallFunction(c->callback, "NO",
1465                                     cpy_oconfig_to_pyconfig(item, NULL),
1466                                     c->data); /* New reference. */
1467       if (ret == NULL) {
1468         cpy_log_exception("loading module");
1469         status = 1;
1470       } else
1471         Py_DECREF(ret);
1472     } else {
1473       ERROR("python plugin: Unknown config key \"%s\".", item->key);
1474       status = 1;
1475     }
1476   }
1477   return status;
1478 }
1479
1480 void module_register(void) {
1481   plugin_register_complex_config("python", cpy_config);
1482   plugin_register_init("python", cpy_init);
1483   plugin_register_shutdown("python", cpy_shutdown);
1484 }