python plugin: Passed through clang-format
[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;
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         temp = PyObject_CallFunctionObjArgs((void *)&SignedType,
465                                             PyLong_FromLongLong(si),
466                                             (void *)0); /* New reference. */
467         PyDict_SetItemString(dict, table[i], temp);
468         Py_XDECREF(temp);
469       } else if (type == MD_TYPE_UNSIGNED_INT) {
470         if (meta_data_get_unsigned_int(meta, table[i], &ui))
471           continue;
472         temp = PyObject_CallFunctionObjArgs((void *)&UnsignedType,
473                                             PyLong_FromUnsignedLongLong(ui),
474                                             (void *)0); /* New reference. */
475         PyDict_SetItemString(dict, table[i], temp);
476         Py_XDECREF(temp);
477       } else if (type == MD_TYPE_DOUBLE) {
478         if (meta_data_get_double(meta, table[i], &d))
479           continue;
480         temp = PyFloat_FromDouble(d); /* New reference. */
481         PyDict_SetItemString(dict, table[i], temp);
482         Py_XDECREF(temp);
483       } else if (type == MD_TYPE_BOOLEAN) {
484         if (meta_data_get_boolean(meta, table[i], &b))
485           continue;
486         if (b)
487           PyDict_SetItemString(dict, table[i], Py_True);
488         else
489           PyDict_SetItemString(dict, table[i], Py_False);
490       }
491       free(table[i]);
492     }
493     free(table);
494   }
495   v = (Values *)Values_New(); /* New reference. */
496   sstrncpy(v->data.host, value_list->host, sizeof(v->data.host));
497   sstrncpy(v->data.type, value_list->type, sizeof(v->data.type));
498   sstrncpy(v->data.type_instance, value_list->type_instance,
499            sizeof(v->data.type_instance));
500   sstrncpy(v->data.plugin, value_list->plugin, sizeof(v->data.plugin));
501   sstrncpy(v->data.plugin_instance, value_list->plugin_instance,
502            sizeof(v->data.plugin_instance));
503   v->data.time = CDTIME_T_TO_DOUBLE(value_list->time);
504   v->interval = CDTIME_T_TO_DOUBLE(value_list->interval);
505   Py_CLEAR(v->values);
506   v->values = list;
507   Py_CLEAR(v->meta);
508   v->meta = dict; /* Steals a reference. */
509   ret = PyObject_CallFunctionObjArgs(c->callback, v, c->data,
510                                      (void *)0); /* New reference. */
511   Py_XDECREF(v);
512   if (ret == NULL) {
513     cpy_log_exception("write callback");
514   } else {
515     Py_DECREF(ret);
516   }
517   CPY_RELEASE_THREADS
518   return 0;
519 }
520
521 static int cpy_notification_callback(const notification_t *notification,
522                                      user_data_t *data) {
523   cpy_callback_t *c = data->data;
524   PyObject *ret, *notify;
525   Notification *n;
526
527   CPY_LOCK_THREADS
528   notify = Notification_New(); /* New reference. */
529   n = (Notification *)notify;
530   sstrncpy(n->data.host, notification->host, sizeof(n->data.host));
531   sstrncpy(n->data.type, notification->type, sizeof(n->data.type));
532   sstrncpy(n->data.type_instance, notification->type_instance,
533            sizeof(n->data.type_instance));
534   sstrncpy(n->data.plugin, notification->plugin, sizeof(n->data.plugin));
535   sstrncpy(n->data.plugin_instance, notification->plugin_instance,
536            sizeof(n->data.plugin_instance));
537   n->data.time = CDTIME_T_TO_DOUBLE(notification->time);
538   sstrncpy(n->message, notification->message, sizeof(n->message));
539   n->severity = notification->severity;
540   ret = PyObject_CallFunctionObjArgs(c->callback, n, c->data,
541                                      (void *)0); /* New reference. */
542   Py_XDECREF(notify);
543   if (ret == NULL) {
544     cpy_log_exception("notification callback");
545   } else {
546     Py_DECREF(ret);
547   }
548   CPY_RELEASE_THREADS
549   return 0;
550 }
551
552 static void cpy_log_callback(int severity, const char *message,
553                              user_data_t *data) {
554   cpy_callback_t *c = data->data;
555   PyObject *ret, *text;
556
557   CPY_LOCK_THREADS
558   text = cpy_string_to_unicode_or_bytes(message); /* New reference. */
559   if (c->data == NULL)
560     ret = PyObject_CallFunction(
561         c->callback, "iN", severity,
562         text); /* New reference. Steals a reference from "text". */
563   else
564     ret = PyObject_CallFunction(
565         c->callback, "iNO", severity, text,
566         c->data); /* New reference. Steals a reference from "text". */
567
568   if (ret == NULL) {
569     /* FIXME */
570     /* Do we really want to trigger a log callback because a log callback
571      * failed?
572      * Probably not. */
573     PyErr_Print();
574     /* In case someone wanted to be clever, replaced stderr and failed at that.
575      */
576     PyErr_Clear();
577   } else {
578     Py_DECREF(ret);
579   }
580   CPY_RELEASE_THREADS
581 }
582
583 static void cpy_flush_callback(int timeout, const char *id, user_data_t *data) {
584   cpy_callback_t *c = data->data;
585   PyObject *ret, *text;
586
587   CPY_LOCK_THREADS
588   if (id) {
589     text = cpy_string_to_unicode_or_bytes(id);
590   } else {
591     text = Py_None;
592     Py_INCREF(text);
593   }
594   if (c->data == NULL)
595     ret = PyObject_CallFunction(c->callback, "iN", timeout,
596                                 text); /* New reference. */
597   else
598     ret = PyObject_CallFunction(c->callback, "iNO", timeout, text,
599                                 c->data); /* New reference. */
600
601   if (ret == NULL) {
602     cpy_log_exception("flush callback");
603   } else {
604     Py_DECREF(ret);
605   }
606   CPY_RELEASE_THREADS
607 }
608
609 static PyObject *cpy_register_generic(cpy_callback_t **list_head,
610                                       PyObject *args, PyObject *kwds) {
611   char buf[512];
612   cpy_callback_t *c;
613   char *name = NULL;
614   PyObject *callback = NULL, *data = NULL, *mod = NULL;
615   static char *kwlist[] = {"callback", "data", "name", NULL};
616
617   if (PyArg_ParseTupleAndKeywords(args, kwds, "O|Oet", kwlist, &callback, &data,
618                                   NULL, &name) == 0)
619     return NULL;
620   if (PyCallable_Check(callback) == 0) {
621     PyMem_Free(name);
622     PyErr_SetString(PyExc_TypeError, "callback needs a be a callable object.");
623     return NULL;
624   }
625   cpy_build_name(buf, sizeof(buf), callback, name);
626
627   Py_INCREF(callback);
628   Py_XINCREF(data);
629
630   c = calloc(1, sizeof(*c));
631   if (c == NULL)
632     return NULL;
633
634   c->name = strdup(buf);
635   c->callback = callback;
636   c->data = data;
637   c->next = *list_head;
638   ++cpy_num_callbacks;
639   *list_head = c;
640   Py_XDECREF(mod);
641   PyMem_Free(name);
642   return cpy_string_to_unicode_or_bytes(buf);
643 }
644
645 static PyObject *float_or_none(float number) {
646   if (isnan(number)) {
647     Py_RETURN_NONE;
648   }
649   return PyFloat_FromDouble(number);
650 }
651
652 static PyObject *cpy_get_dataset(PyObject *self, PyObject *args) {
653   char *name;
654   const data_set_t *ds;
655   PyObject *list, *tuple;
656
657   if (PyArg_ParseTuple(args, "et", NULL, &name) == 0)
658     return NULL;
659   ds = plugin_get_ds(name);
660   PyMem_Free(name);
661   if (ds == NULL) {
662     PyErr_Format(PyExc_TypeError, "Dataset %s not found", name);
663     return NULL;
664   }
665   list = PyList_New(ds->ds_num); /* New reference. */
666   for (size_t i = 0; i < ds->ds_num; ++i) {
667     tuple = PyTuple_New(4);
668     PyTuple_SET_ITEM(tuple, 0, cpy_string_to_unicode_or_bytes(ds->ds[i].name));
669     PyTuple_SET_ITEM(tuple, 1, cpy_string_to_unicode_or_bytes(
670                                    DS_TYPE_TO_STRING(ds->ds[i].type)));
671     PyTuple_SET_ITEM(tuple, 2, float_or_none(ds->ds[i].min));
672     PyTuple_SET_ITEM(tuple, 3, float_or_none(ds->ds[i].max));
673     PyList_SET_ITEM(list, i, tuple);
674   }
675   return list;
676 }
677
678 static PyObject *cpy_flush(PyObject *self, PyObject *args, PyObject *kwds) {
679   int timeout = -1;
680   char *plugin = NULL, *identifier = NULL;
681   static char *kwlist[] = {"plugin", "timeout", "identifier", NULL};
682
683   if (PyArg_ParseTupleAndKeywords(args, kwds, "|etiet", kwlist, NULL, &plugin,
684                                   &timeout, NULL, &identifier) == 0)
685     return NULL;
686   Py_BEGIN_ALLOW_THREADS;
687   plugin_flush(plugin, timeout, identifier);
688   Py_END_ALLOW_THREADS;
689   PyMem_Free(plugin);
690   PyMem_Free(identifier);
691   Py_RETURN_NONE;
692 }
693
694 static PyObject *cpy_register_config(PyObject *self, PyObject *args,
695                                      PyObject *kwds) {
696   return cpy_register_generic(&cpy_config_callbacks, args, kwds);
697 }
698
699 static PyObject *cpy_register_init(PyObject *self, PyObject *args,
700                                    PyObject *kwds) {
701   return cpy_register_generic(&cpy_init_callbacks, args, kwds);
702 }
703
704 typedef int reg_function_t(const char *name, void *callback, void *data);
705
706 static PyObject *cpy_register_generic_userdata(void *reg, void *handler,
707                                                PyObject *args, PyObject *kwds) {
708   char buf[512];
709   reg_function_t *register_function = (reg_function_t *)reg;
710   cpy_callback_t *c = NULL;
711   char *name = NULL;
712   PyObject *callback = NULL, *data = NULL;
713   static char *kwlist[] = {"callback", "data", "name", NULL};
714
715   if (PyArg_ParseTupleAndKeywords(args, kwds, "O|Oet", kwlist, &callback, &data,
716                                   NULL, &name) == 0)
717     return NULL;
718   if (PyCallable_Check(callback) == 0) {
719     PyMem_Free(name);
720     PyErr_SetString(PyExc_TypeError, "callback needs a be a callable object.");
721     return NULL;
722   }
723   cpy_build_name(buf, sizeof(buf), callback, name);
724   PyMem_Free(name);
725
726   Py_INCREF(callback);
727   Py_XINCREF(data);
728
729   c = calloc(1, sizeof(*c));
730   if (c == NULL)
731     return NULL;
732
733   c->name = strdup(buf);
734   c->callback = callback;
735   c->data = data;
736   c->next = NULL;
737
738   register_function(buf, handler,
739                     &(user_data_t){
740                         .data = c, .free_func = cpy_destroy_user_data,
741                     });
742
743   ++cpy_num_callbacks;
744   return cpy_string_to_unicode_or_bytes(buf);
745 }
746
747 static PyObject *cpy_register_read(PyObject *self, PyObject *args,
748                                    PyObject *kwds) {
749   char buf[512];
750   cpy_callback_t *c = NULL;
751   double interval = 0;
752   char *name = NULL;
753   PyObject *callback = NULL, *data = NULL;
754   static char *kwlist[] = {"callback", "interval", "data", "name", NULL};
755
756   if (PyArg_ParseTupleAndKeywords(args, kwds, "O|dOet", kwlist, &callback,
757                                   &interval, &data, NULL, &name) == 0)
758     return NULL;
759   if (PyCallable_Check(callback) == 0) {
760     PyMem_Free(name);
761     PyErr_SetString(PyExc_TypeError, "callback needs a be a callable object.");
762     return NULL;
763   }
764   cpy_build_name(buf, sizeof(buf), callback, name);
765   PyMem_Free(name);
766
767   Py_INCREF(callback);
768   Py_XINCREF(data);
769
770   c = calloc(1, sizeof(*c));
771   if (c == NULL)
772     return NULL;
773
774   c->name = strdup(buf);
775   c->callback = callback;
776   c->data = data;
777   c->next = NULL;
778
779   plugin_register_complex_read(
780       /* group = */ "python", buf, cpy_read_callback,
781       DOUBLE_TO_CDTIME_T(interval),
782       &(user_data_t){
783           .data = c, .free_func = cpy_destroy_user_data,
784       });
785   ++cpy_num_callbacks;
786   return cpy_string_to_unicode_or_bytes(buf);
787 }
788
789 static PyObject *cpy_register_log(PyObject *self, PyObject *args,
790                                   PyObject *kwds) {
791   return cpy_register_generic_userdata((void *)plugin_register_log,
792                                        (void *)cpy_log_callback, args, kwds);
793 }
794
795 static PyObject *cpy_register_write(PyObject *self, PyObject *args,
796                                     PyObject *kwds) {
797   return cpy_register_generic_userdata((void *)plugin_register_write,
798                                        (void *)cpy_write_callback, args, kwds);
799 }
800
801 static PyObject *cpy_register_notification(PyObject *self, PyObject *args,
802                                            PyObject *kwds) {
803   return cpy_register_generic_userdata((void *)plugin_register_notification,
804                                        (void *)cpy_notification_callback, args,
805                                        kwds);
806 }
807
808 static PyObject *cpy_register_flush(PyObject *self, PyObject *args,
809                                     PyObject *kwds) {
810   return cpy_register_generic_userdata((void *)plugin_register_flush,
811                                        (void *)cpy_flush_callback, args, kwds);
812 }
813
814 static PyObject *cpy_register_shutdown(PyObject *self, PyObject *args,
815                                        PyObject *kwds) {
816   return cpy_register_generic(&cpy_shutdown_callbacks, args, kwds);
817 }
818
819 static PyObject *cpy_error(PyObject *self, PyObject *args) {
820   char *text;
821   if (PyArg_ParseTuple(args, "et", NULL, &text) == 0)
822     return NULL;
823   Py_BEGIN_ALLOW_THREADS;
824   plugin_log(LOG_ERR, "%s", text);
825   Py_END_ALLOW_THREADS;
826   PyMem_Free(text);
827   Py_RETURN_NONE;
828 }
829
830 static PyObject *cpy_warning(PyObject *self, PyObject *args) {
831   char *text;
832   if (PyArg_ParseTuple(args, "et", NULL, &text) == 0)
833     return NULL;
834   Py_BEGIN_ALLOW_THREADS;
835   plugin_log(LOG_WARNING, "%s", text);
836   Py_END_ALLOW_THREADS;
837   PyMem_Free(text);
838   Py_RETURN_NONE;
839 }
840
841 static PyObject *cpy_notice(PyObject *self, PyObject *args) {
842   char *text;
843   if (PyArg_ParseTuple(args, "et", NULL, &text) == 0)
844     return NULL;
845   Py_BEGIN_ALLOW_THREADS;
846   plugin_log(LOG_NOTICE, "%s", text);
847   Py_END_ALLOW_THREADS;
848   PyMem_Free(text);
849   Py_RETURN_NONE;
850 }
851
852 static PyObject *cpy_info(PyObject *self, PyObject *args) {
853   char *text;
854   if (PyArg_ParseTuple(args, "et", NULL, &text) == 0)
855     return NULL;
856   Py_BEGIN_ALLOW_THREADS;
857   plugin_log(LOG_INFO, "%s", text);
858   Py_END_ALLOW_THREADS;
859   PyMem_Free(text);
860   Py_RETURN_NONE;
861 }
862
863 static PyObject *cpy_debug(PyObject *self, PyObject *args) {
864 #ifdef COLLECT_DEBUG
865   char *text;
866   if (PyArg_ParseTuple(args, "et", NULL, &text) == 0)
867     return NULL;
868   Py_BEGIN_ALLOW_THREADS;
869   plugin_log(LOG_DEBUG, "%s", text);
870   Py_END_ALLOW_THREADS;
871   PyMem_Free(text);
872 #endif
873   Py_RETURN_NONE;
874 }
875
876 static PyObject *cpy_unregister_generic(cpy_callback_t **list_head,
877                                         PyObject *arg, const char *desc) {
878   char buf[512];
879   const char *name;
880   cpy_callback_t *prev = NULL, *tmp;
881
882   Py_INCREF(arg);
883   name = cpy_unicode_or_bytes_to_string(&arg);
884   if (name == NULL) {
885     PyErr_Clear();
886     if (!PyCallable_Check(arg)) {
887       PyErr_SetString(PyExc_TypeError, "This function needs a string or a "
888                                        "callable object as its only "
889                                        "parameter.");
890       Py_DECREF(arg);
891       return NULL;
892     }
893     cpy_build_name(buf, sizeof(buf), arg, NULL);
894     name = buf;
895   }
896   for (tmp = *list_head; tmp; prev = tmp, tmp = tmp->next)
897     if (strcmp(name, tmp->name) == 0)
898       break;
899
900   Py_DECREF(arg);
901   if (tmp == NULL) {
902     PyErr_Format(PyExc_RuntimeError, "Unable to unregister %s callback '%s'.",
903                  desc, name);
904     return NULL;
905   }
906   /* Yes, this is actually safe. To call this function the caller has to
907    * hold the GIL. Well, safe as long as there is only one GIL anyway ... */
908   if (prev == NULL)
909     *list_head = tmp->next;
910   else
911     prev->next = tmp->next;
912   cpy_destroy_user_data(tmp);
913   Py_RETURN_NONE;
914 }
915
916 static void cpy_unregister_list(cpy_callback_t **list_head) {
917   cpy_callback_t *cur, *next;
918   for (cur = *list_head; cur; cur = next) {
919     next = cur->next;
920     cpy_destroy_user_data(cur);
921   }
922   *list_head = NULL;
923 }
924
925 typedef int cpy_unregister_function_t(const char *name);
926
927 static PyObject *
928 cpy_unregister_generic_userdata(cpy_unregister_function_t *unreg, PyObject *arg,
929                                 const char *desc) {
930   char buf[512];
931   const char *name;
932
933   Py_INCREF(arg);
934   name = cpy_unicode_or_bytes_to_string(&arg);
935   if (name == NULL) {
936     PyErr_Clear();
937     if (!PyCallable_Check(arg)) {
938       PyErr_SetString(PyExc_TypeError, "This function needs a string or a "
939                                        "callable object as its only "
940                                        "parameter.");
941       Py_DECREF(arg);
942       return NULL;
943     }
944     cpy_build_name(buf, sizeof(buf), arg, NULL);
945     name = buf;
946   }
947   if (unreg(name) == 0) {
948     Py_DECREF(arg);
949     Py_RETURN_NONE;
950   }
951   PyErr_Format(PyExc_RuntimeError, "Unable to unregister %s callback '%s'.",
952                desc, name);
953   Py_DECREF(arg);
954   return NULL;
955 }
956
957 static PyObject *cpy_unregister_log(PyObject *self, PyObject *arg) {
958   return cpy_unregister_generic_userdata(plugin_unregister_log, arg, "log");
959 }
960
961 static PyObject *cpy_unregister_init(PyObject *self, PyObject *arg) {
962   return cpy_unregister_generic(&cpy_init_callbacks, arg, "init");
963 }
964
965 static PyObject *cpy_unregister_config(PyObject *self, PyObject *arg) {
966   return cpy_unregister_generic(&cpy_config_callbacks, arg, "config");
967 }
968
969 static PyObject *cpy_unregister_read(PyObject *self, PyObject *arg) {
970   return cpy_unregister_generic_userdata(plugin_unregister_read, arg, "read");
971 }
972
973 static PyObject *cpy_unregister_write(PyObject *self, PyObject *arg) {
974   return cpy_unregister_generic_userdata(plugin_unregister_write, arg, "write");
975 }
976
977 static PyObject *cpy_unregister_notification(PyObject *self, PyObject *arg) {
978   return cpy_unregister_generic_userdata(plugin_unregister_notification, arg,
979                                          "notification");
980 }
981
982 static PyObject *cpy_unregister_flush(PyObject *self, PyObject *arg) {
983   return cpy_unregister_generic_userdata(plugin_unregister_flush, arg, "flush");
984 }
985
986 static PyObject *cpy_unregister_shutdown(PyObject *self, PyObject *arg) {
987   return cpy_unregister_generic(&cpy_shutdown_callbacks, arg, "shutdown");
988 }
989
990 static PyMethodDef cpy_methods[] = {
991     {"debug", cpy_debug, METH_VARARGS, log_doc},
992     {"info", cpy_info, METH_VARARGS, log_doc},
993     {"notice", cpy_notice, METH_VARARGS, log_doc},
994     {"warning", cpy_warning, METH_VARARGS, log_doc},
995     {"error", cpy_error, METH_VARARGS, log_doc},
996     {"get_dataset", (PyCFunction)cpy_get_dataset, METH_VARARGS, get_ds_doc},
997     {"flush", (PyCFunction)cpy_flush, METH_VARARGS | METH_KEYWORDS, flush_doc},
998     {"register_log", (PyCFunction)cpy_register_log,
999      METH_VARARGS | METH_KEYWORDS, reg_log_doc},
1000     {"register_init", (PyCFunction)cpy_register_init,
1001      METH_VARARGS | METH_KEYWORDS, reg_init_doc},
1002     {"register_config", (PyCFunction)cpy_register_config,
1003      METH_VARARGS | METH_KEYWORDS, reg_config_doc},
1004     {"register_read", (PyCFunction)cpy_register_read,
1005      METH_VARARGS | METH_KEYWORDS, reg_read_doc},
1006     {"register_write", (PyCFunction)cpy_register_write,
1007      METH_VARARGS | METH_KEYWORDS, reg_write_doc},
1008     {"register_notification", (PyCFunction)cpy_register_notification,
1009      METH_VARARGS | METH_KEYWORDS, reg_notification_doc},
1010     {"register_flush", (PyCFunction)cpy_register_flush,
1011      METH_VARARGS | METH_KEYWORDS, reg_flush_doc},
1012     {"register_shutdown", (PyCFunction)cpy_register_shutdown,
1013      METH_VARARGS | METH_KEYWORDS, reg_shutdown_doc},
1014     {"unregister_log", cpy_unregister_log, METH_O, unregister_doc},
1015     {"unregister_init", cpy_unregister_init, METH_O, unregister_doc},
1016     {"unregister_config", cpy_unregister_config, METH_O, unregister_doc},
1017     {"unregister_read", cpy_unregister_read, METH_O, unregister_doc},
1018     {"unregister_write", cpy_unregister_write, METH_O, unregister_doc},
1019     {"unregister_notification", cpy_unregister_notification, METH_O,
1020      unregister_doc},
1021     {"unregister_flush", cpy_unregister_flush, METH_O, unregister_doc},
1022     {"unregister_shutdown", cpy_unregister_shutdown, METH_O, unregister_doc},
1023     {0, 0, 0, 0}};
1024
1025 static int cpy_shutdown(void) {
1026   PyObject *ret;
1027
1028   if (!state) {
1029     printf(
1030         "================================================================\n");
1031     printf(
1032         "collectd shutdown while running an interactive session. This will\n");
1033     printf("probably leave your terminal in a mess.\n");
1034     printf("Run the command \"reset\" to get it back into a usable state.\n");
1035     printf("You can press Ctrl+D in the interactive session to\n");
1036     printf("close collectd and avoid this problem in the future.\n");
1037     printf(
1038         "================================================================\n");
1039   }
1040
1041   CPY_LOCK_THREADS
1042
1043   for (cpy_callback_t *c = cpy_shutdown_callbacks; c; c = c->next) {
1044     ret = PyObject_CallFunctionObjArgs(c->callback, c->data,
1045                                        (void *)0); /* New reference. */
1046     if (ret == NULL)
1047       cpy_log_exception("shutdown callback");
1048     else
1049       Py_DECREF(ret);
1050   }
1051   PyErr_Print();
1052
1053   Py_BEGIN_ALLOW_THREADS;
1054   cpy_unregister_list(&cpy_config_callbacks);
1055   cpy_unregister_list(&cpy_init_callbacks);
1056   cpy_unregister_list(&cpy_shutdown_callbacks);
1057   cpy_shutdown_triggered = 1;
1058   Py_END_ALLOW_THREADS;
1059
1060   if (!cpy_num_callbacks) {
1061     Py_Finalize();
1062     return 0;
1063   }
1064
1065   CPY_RELEASE_THREADS
1066   return 0;
1067 }
1068
1069 static void *cpy_interactive(void *pipefd) {
1070   PyOS_sighandler_t cur_sig;
1071
1072   /* Signal handler in a plugin? Bad stuff, but the best way to
1073    * handle it I guess. In an interactive session people will
1074    * press Ctrl+C at some time, which will generate a SIGINT.
1075    * This will cause collectd to shutdown, thus killing the
1076    * interactive interpreter, and leaving the terminal in a
1077    * mess. Chances are, this isn't what the user wanted to do.
1078    *
1079    * So this is the plan:
1080    * 1. Restore Python's own signal handler
1081    * 2. Tell Python we just forked so it will accept this thread
1082    *    as the main one. No version of Python will ever handle
1083    *    interrupts anywhere but in the main thread.
1084    * 3. After the interactive loop is done, restore collectd's
1085    *    SIGINT handler.
1086    * 4. Raise SIGINT for a clean shutdown. The signal is sent to
1087    *    the main thread to ensure it wakes up the main interval
1088    *    sleep so that collectd shuts down immediately not in 10
1089    *    seconds.
1090    *
1091    * This will make sure that SIGINT won't kill collectd but
1092    * still interrupt syscalls like sleep and pause. */
1093
1094   if (PyImport_ImportModule("readline") == NULL) {
1095     /* This interactive session will suck. */
1096     cpy_log_exception("interactive session init");
1097   }
1098   cur_sig = PyOS_setsig(SIGINT, python_sigint_handler);
1099   PyOS_AfterFork();
1100   PyEval_InitThreads();
1101   close(*(int *)pipefd);
1102   PyRun_InteractiveLoop(stdin, "<stdin>");
1103   PyOS_setsig(SIGINT, cur_sig);
1104   PyErr_Print();
1105   state = PyEval_SaveThread();
1106   NOTICE("python: Interactive interpreter exited, stopping collectd ...");
1107   pthread_kill(main_thread, SIGINT);
1108   return NULL;
1109 }
1110
1111 static int cpy_init(void) {
1112   PyObject *ret;
1113   int pipefd[2];
1114   char buf;
1115   static pthread_t thread;
1116
1117   if (!Py_IsInitialized()) {
1118     WARNING("python: Plugin loaded but not configured.");
1119     plugin_unregister_shutdown("python");
1120     Py_Finalize();
1121     return 0;
1122   }
1123   main_thread = pthread_self();
1124   if (do_interactive) {
1125     if (pipe(pipefd)) {
1126       ERROR("python: Unable to create pipe.");
1127       return 1;
1128     }
1129     if (plugin_thread_create(&thread, NULL, cpy_interactive, pipefd + 1,
1130                              "python interpreter")) {
1131       ERROR("python: Error creating thread for interactive interpreter.");
1132     }
1133     if (read(pipefd[0], &buf, 1))
1134       ;
1135     (void)close(pipefd[0]);
1136   } else {
1137     PyEval_InitThreads();
1138     state = PyEval_SaveThread();
1139   }
1140   CPY_LOCK_THREADS
1141   for (cpy_callback_t *c = cpy_init_callbacks; c; c = c->next) {
1142     ret = PyObject_CallFunctionObjArgs(c->callback, c->data,
1143                                        (void *)0); /* New reference. */
1144     if (ret == NULL)
1145       cpy_log_exception("init callback");
1146     else
1147       Py_DECREF(ret);
1148   }
1149   CPY_RELEASE_THREADS
1150
1151   return 0;
1152 }
1153
1154 static PyObject *cpy_oconfig_to_pyconfig(oconfig_item_t *ci, PyObject *parent) {
1155   PyObject *item, *values, *children, *tmp;
1156
1157   if (parent == NULL)
1158     parent = Py_None;
1159
1160   values = PyTuple_New(ci->values_num); /* New reference. */
1161   for (int i = 0; i < ci->values_num; ++i) {
1162     if (ci->values[i].type == OCONFIG_TYPE_STRING) {
1163       PyTuple_SET_ITEM(values, i, cpy_string_to_unicode_or_bytes(
1164                                       ci->values[i].value.string));
1165     } else if (ci->values[i].type == OCONFIG_TYPE_NUMBER) {
1166       PyTuple_SET_ITEM(values, i,
1167                        PyFloat_FromDouble(ci->values[i].value.number));
1168     } else if (ci->values[i].type == OCONFIG_TYPE_BOOLEAN) {
1169       PyTuple_SET_ITEM(values, i, PyBool_FromLong(ci->values[i].value.boolean));
1170     }
1171   }
1172
1173   tmp = cpy_string_to_unicode_or_bytes(ci->key);
1174   item = PyObject_CallFunction((void *)&ConfigType, "NONO", tmp, parent, values,
1175                                Py_None);
1176   if (item == NULL)
1177     return NULL;
1178   children = PyTuple_New(ci->children_num); /* New reference. */
1179   for (int i = 0; i < ci->children_num; ++i) {
1180     PyTuple_SET_ITEM(children, i,
1181                      cpy_oconfig_to_pyconfig(ci->children + i, item));
1182   }
1183   tmp = ((Config *)item)->children;
1184   ((Config *)item)->children = children;
1185   Py_XDECREF(tmp);
1186   return item;
1187 }
1188
1189 #ifdef IS_PY3K
1190 static struct PyModuleDef collectdmodule = {
1191     PyModuleDef_HEAD_INIT, "collectd",  /* name of module */
1192     "The python interface to collectd", /* module documentation, may be NULL */
1193     -1, cpy_methods};
1194
1195 PyMODINIT_FUNC PyInit_collectd(void) {
1196   return PyModule_Create(&collectdmodule);
1197 }
1198 #endif
1199
1200 static int cpy_init_python(void) {
1201   PyOS_sighandler_t cur_sig;
1202   PyObject *sys, *errordict;
1203   PyObject *module;
1204
1205 #ifdef IS_PY3K
1206   wchar_t *argv = L"";
1207   /* Add a builtin module, before Py_Initialize */
1208   PyImport_AppendInittab("collectd", PyInit_collectd);
1209 #else
1210   char *argv = "";
1211 #endif
1212
1213   /* Chances are the current signal handler is already SIG_DFL, but let's make
1214    * sure. */
1215   cur_sig = PyOS_setsig(SIGINT, SIG_DFL);
1216   Py_Initialize();
1217   python_sigint_handler = PyOS_setsig(SIGINT, cur_sig);
1218
1219   PyType_Ready(&ConfigType);
1220   PyType_Ready(&PluginDataType);
1221   ValuesType.tp_base = &PluginDataType;
1222   PyType_Ready(&ValuesType);
1223   NotificationType.tp_base = &PluginDataType;
1224   PyType_Ready(&NotificationType);
1225   SignedType.tp_base = &PyLong_Type;
1226   PyType_Ready(&SignedType);
1227   UnsignedType.tp_base = &PyLong_Type;
1228   PyType_Ready(&UnsignedType);
1229   errordict = PyDict_New();
1230   PyDict_SetItemString(
1231       errordict, "__doc__",
1232       cpy_string_to_unicode_or_bytes(CollectdError_doc)); /* New reference. */
1233   CollectdError = PyErr_NewException("collectd.CollectdError", NULL, errordict);
1234   sys = PyImport_ImportModule("sys"); /* New reference. */
1235   if (sys == NULL) {
1236     cpy_log_exception("python initialization");
1237     return 1;
1238   }
1239   sys_path = PyObject_GetAttrString(sys, "path"); /* New reference. */
1240   Py_DECREF(sys);
1241   if (sys_path == NULL) {
1242     cpy_log_exception("python initialization");
1243     return 1;
1244   }
1245   PySys_SetArgv(1, &argv);
1246   PyList_SetSlice(sys_path, 0, 1, NULL);
1247
1248 #ifdef IS_PY3K
1249   module = PyImport_ImportModule("collectd");
1250 #else
1251   module = Py_InitModule("collectd", cpy_methods); /* Borrowed reference. */
1252 #endif
1253   PyModule_AddObject(module, "Config",
1254                      (void *)&ConfigType); /* Steals a reference. */
1255   PyModule_AddObject(module, "Values",
1256                      (void *)&ValuesType); /* Steals a reference. */
1257   PyModule_AddObject(module, "Notification",
1258                      (void *)&NotificationType); /* Steals a reference. */
1259   PyModule_AddObject(module, "Signed",
1260                      (void *)&SignedType); /* Steals a reference. */
1261   PyModule_AddObject(module, "Unsigned",
1262                      (void *)&UnsignedType); /* Steals a reference. */
1263   Py_XINCREF(CollectdError);
1264   PyModule_AddObject(module, "CollectdError",
1265                      CollectdError); /* Steals a reference. */
1266   PyModule_AddIntConstant(module, "LOG_DEBUG", LOG_DEBUG);
1267   PyModule_AddIntConstant(module, "LOG_INFO", LOG_INFO);
1268   PyModule_AddIntConstant(module, "LOG_NOTICE", LOG_NOTICE);
1269   PyModule_AddIntConstant(module, "LOG_WARNING", LOG_WARNING);
1270   PyModule_AddIntConstant(module, "LOG_ERROR", LOG_ERR);
1271   PyModule_AddIntConstant(module, "NOTIF_FAILURE", NOTIF_FAILURE);
1272   PyModule_AddIntConstant(module, "NOTIF_WARNING", NOTIF_WARNING);
1273   PyModule_AddIntConstant(module, "NOTIF_OKAY", NOTIF_OKAY);
1274   PyModule_AddStringConstant(module, "DS_TYPE_COUNTER",
1275                              DS_TYPE_TO_STRING(DS_TYPE_COUNTER));
1276   PyModule_AddStringConstant(module, "DS_TYPE_GAUGE",
1277                              DS_TYPE_TO_STRING(DS_TYPE_GAUGE));
1278   PyModule_AddStringConstant(module, "DS_TYPE_DERIVE",
1279                              DS_TYPE_TO_STRING(DS_TYPE_DERIVE));
1280   PyModule_AddStringConstant(module, "DS_TYPE_ABSOLUTE",
1281                              DS_TYPE_TO_STRING(DS_TYPE_ABSOLUTE));
1282   return 0;
1283 }
1284
1285 static int cpy_config(oconfig_item_t *ci) {
1286   PyObject *tb;
1287   int status = 0;
1288
1289   /* Ok in theory we shouldn't do initialization at this point
1290    * but we have to. In order to give python scripts a chance
1291    * to register a config callback we need to be able to execute
1292    * python code during the config callback so we have to start
1293    * the interpreter here. */
1294   /* Do *not* use the python "thread" module at this point! */
1295
1296   if (!Py_IsInitialized() && cpy_init_python())
1297     return 1;
1298
1299   for (int i = 0; i < ci->children_num; ++i) {
1300     oconfig_item_t *item = ci->children + i;
1301
1302     if (strcasecmp(item->key, "Interactive") == 0) {
1303       if (cf_util_get_boolean(item, &do_interactive) != 0) {
1304         status = 1;
1305         continue;
1306       }
1307     } else if (strcasecmp(item->key, "Encoding") == 0) {
1308       char *encoding = NULL;
1309       if (cf_util_get_string(item, &encoding) != 0) {
1310         status = 1;
1311         continue;
1312       }
1313 #ifdef IS_PY3K
1314       ERROR("python: \"Encoding\" was used in the config file but Python3 was "
1315             "used, which does not support changing encodings");
1316       status = 1;
1317       sfree(encoding);
1318       continue;
1319 #else
1320       /* Why is this even necessary? And undocumented? */
1321       if (PyUnicode_SetDefaultEncoding(encoding)) {
1322         cpy_log_exception("setting default encoding");
1323         status = 1;
1324       }
1325 #endif
1326       sfree(encoding);
1327     } else if (strcasecmp(item->key, "LogTraces") == 0) {
1328       _Bool log_traces;
1329       if (cf_util_get_boolean(item, &log_traces) != 0) {
1330         status = 1;
1331         continue;
1332       }
1333       if (!log_traces) {
1334         Py_XDECREF(cpy_format_exception);
1335         cpy_format_exception = NULL;
1336         continue;
1337       }
1338       if (cpy_format_exception)
1339         continue;
1340       tb = PyImport_ImportModule("traceback"); /* New reference. */
1341       if (tb == NULL) {
1342         cpy_log_exception("python initialization");
1343         status = 1;
1344         continue;
1345       }
1346       cpy_format_exception =
1347           PyObject_GetAttrString(tb, "format_exception"); /* New reference. */
1348       Py_DECREF(tb);
1349       if (cpy_format_exception == NULL) {
1350         cpy_log_exception("python initialization");
1351         status = 1;
1352       }
1353     } else if (strcasecmp(item->key, "ModulePath") == 0) {
1354       char *dir = NULL;
1355       PyObject *dir_object;
1356
1357       if (cf_util_get_string(item, &dir) != 0) {
1358         status = 1;
1359         continue;
1360       }
1361       dir_object = cpy_string_to_unicode_or_bytes(dir); /* New reference. */
1362       if (dir_object == NULL) {
1363         ERROR("python plugin: Unable to convert \"%s\" to "
1364               "a python object.",
1365               dir);
1366         free(dir);
1367         cpy_log_exception("python initialization");
1368         status = 1;
1369         continue;
1370       }
1371       if (PyList_Insert(sys_path, 0, dir_object) != 0) {
1372         ERROR("python plugin: Unable to prepend \"%s\" to "
1373               "python module path.",
1374               dir);
1375         cpy_log_exception("python initialization");
1376         status = 1;
1377       }
1378       Py_DECREF(dir_object);
1379       free(dir);
1380     } else if (strcasecmp(item->key, "Import") == 0) {
1381       char *module_name = NULL;
1382       PyObject *module;
1383
1384       if (cf_util_get_string(item, &module_name) != 0) {
1385         status = 1;
1386         continue;
1387       }
1388       module = PyImport_ImportModule(module_name); /* New reference. */
1389       if (module == NULL) {
1390         ERROR("python plugin: Error importing module \"%s\".", module_name);
1391         cpy_log_exception("importing module");
1392         status = 1;
1393       }
1394       free(module_name);
1395       Py_XDECREF(module);
1396     } else if (strcasecmp(item->key, "Module") == 0) {
1397       char *name = NULL;
1398       cpy_callback_t *c;
1399       PyObject *ret;
1400
1401       if (cf_util_get_string(item, &name) != 0) {
1402         status = 1;
1403         continue;
1404       }
1405       for (c = cpy_config_callbacks; c; c = c->next) {
1406         if (strcasecmp(c->name + 7, name) == 0)
1407           break;
1408       }
1409       if (c == NULL) {
1410         WARNING("python plugin: Found a configuration for the \"%s\" plugin, "
1411                 "but the plugin isn't loaded or didn't register "
1412                 "a configuration callback.",
1413                 name);
1414         free(name);
1415         continue;
1416       }
1417       free(name);
1418       if (c->data == NULL)
1419         ret = PyObject_CallFunction(
1420             c->callback, "N",
1421             cpy_oconfig_to_pyconfig(item, NULL)); /* New reference. */
1422       else
1423         ret = PyObject_CallFunction(c->callback, "NO",
1424                                     cpy_oconfig_to_pyconfig(item, NULL),
1425                                     c->data); /* New reference. */
1426       if (ret == NULL) {
1427         cpy_log_exception("loading module");
1428         status = 1;
1429       } else
1430         Py_DECREF(ret);
1431     } else {
1432       ERROR("python plugin: Unknown config key \"%s\".", item->key);
1433       status = 1;
1434     }
1435   }
1436   return status;
1437 }
1438
1439 void module_register(void) {
1440   plugin_register_complex_config("python", cpy_config);
1441   plugin_register_init("python", cpy_init);
1442   plugin_register_shutdown("python", cpy_shutdown);
1443 }