Add CollectdError exception which can be thrown without causing a stacktrace to be...
[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",
333           context, typename, 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,
805                                        args, 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,
975                                          "write");
976 }
977
978 static PyObject *cpy_unregister_notification(PyObject *self, PyObject *arg) {
979   return cpy_unregister_generic_userdata(plugin_unregister_notification, arg,
980                                          "notification");
981 }
982
983 static PyObject *cpy_unregister_flush(PyObject *self, PyObject *arg) {
984   return cpy_unregister_generic_userdata(plugin_unregister_flush, arg,
985                                          "flush");
986 }
987
988 static PyObject *cpy_unregister_shutdown(PyObject *self, PyObject *arg) {
989   return cpy_unregister_generic(&cpy_shutdown_callbacks, arg, "shutdown");
990 }
991
992 static PyMethodDef cpy_methods[] = {
993     {"debug", cpy_debug, METH_VARARGS, log_doc},
994     {"info", cpy_info, METH_VARARGS, log_doc},
995     {"notice", cpy_notice, METH_VARARGS, log_doc},
996     {"warning", cpy_warning, METH_VARARGS, log_doc},
997     {"error", cpy_error, METH_VARARGS, log_doc},
998     {"get_dataset", (PyCFunction)cpy_get_dataset, METH_VARARGS, get_ds_doc},
999     {"flush", (PyCFunction)cpy_flush, METH_VARARGS | METH_KEYWORDS, flush_doc},
1000     {"register_log", (PyCFunction)cpy_register_log,
1001      METH_VARARGS | METH_KEYWORDS, reg_log_doc},
1002     {"register_init", (PyCFunction)cpy_register_init,
1003      METH_VARARGS | METH_KEYWORDS, reg_init_doc},
1004     {"register_config", (PyCFunction)cpy_register_config,
1005      METH_VARARGS | METH_KEYWORDS, reg_config_doc},
1006     {"register_read", (PyCFunction)cpy_register_read,
1007      METH_VARARGS | METH_KEYWORDS, reg_read_doc},
1008     {"register_write", (PyCFunction)cpy_register_write,
1009      METH_VARARGS | METH_KEYWORDS, reg_write_doc},
1010     {"register_notification", (PyCFunction)cpy_register_notification,
1011      METH_VARARGS | METH_KEYWORDS, reg_notification_doc},
1012     {"register_flush", (PyCFunction)cpy_register_flush,
1013      METH_VARARGS | METH_KEYWORDS, reg_flush_doc},
1014     {"register_shutdown", (PyCFunction)cpy_register_shutdown,
1015      METH_VARARGS | METH_KEYWORDS, reg_shutdown_doc},
1016     {"unregister_log", cpy_unregister_log, METH_O, unregister_doc},
1017     {"unregister_init", cpy_unregister_init, METH_O, unregister_doc},
1018     {"unregister_config", cpy_unregister_config, METH_O, unregister_doc},
1019     {"unregister_read", cpy_unregister_read, METH_O, unregister_doc},
1020     {"unregister_write", cpy_unregister_write, METH_O, unregister_doc},
1021     {"unregister_notification", cpy_unregister_notification, METH_O,
1022      unregister_doc},
1023     {"unregister_flush", cpy_unregister_flush, METH_O, unregister_doc},
1024     {"unregister_shutdown", cpy_unregister_shutdown, METH_O, unregister_doc},
1025     {0, 0, 0, 0}};
1026
1027 static int cpy_shutdown(void) {
1028   PyObject *ret;
1029
1030   if (!state) {
1031     printf(
1032         "================================================================\n");
1033     printf(
1034         "collectd shutdown while running an interactive session. This will\n");
1035     printf("probably leave your terminal in a mess.\n");
1036     printf("Run the command \"reset\" to get it back into a usable state.\n");
1037     printf("You can press Ctrl+D in the interactive session to\n");
1038     printf("close collectd and avoid this problem in the future.\n");
1039     printf(
1040         "================================================================\n");
1041   }
1042
1043   CPY_LOCK_THREADS
1044
1045   for (cpy_callback_t *c = cpy_shutdown_callbacks; c; c = c->next) {
1046     ret = PyObject_CallFunctionObjArgs(c->callback, c->data,
1047                                        (void *)0); /* New reference. */
1048     if (ret == NULL)
1049       cpy_log_exception("shutdown callback");
1050     else
1051       Py_DECREF(ret);
1052   }
1053   PyErr_Print();
1054
1055   Py_BEGIN_ALLOW_THREADS
1056   cpy_unregister_list(&cpy_config_callbacks);
1057   cpy_unregister_list(&cpy_init_callbacks);
1058   cpy_unregister_list(&cpy_shutdown_callbacks);
1059   cpy_shutdown_triggered = 1;
1060   Py_END_ALLOW_THREADS
1061
1062   if (!cpy_num_callbacks) {
1063     Py_Finalize();
1064     return 0;
1065   }
1066
1067   CPY_RELEASE_THREADS
1068   return 0;
1069 }
1070
1071 static void *cpy_interactive(void *pipefd) {
1072   PyOS_sighandler_t cur_sig;
1073
1074   /* Signal handler in a plugin? Bad stuff, but the best way to
1075    * handle it I guess. In an interactive session people will
1076    * press Ctrl+C at some time, which will generate a SIGINT.
1077    * This will cause collectd to shutdown, thus killing the
1078    * interactive interpreter, and leaving the terminal in a
1079    * mess. Chances are, this isn't what the user wanted to do.
1080    *
1081    * So this is the plan:
1082    * 1. Restore Python's own signal handler
1083    * 2. Tell Python we just forked so it will accept this thread
1084    *    as the main one. No version of Python will ever handle
1085    *    interrupts anywhere but in the main thread.
1086    * 3. After the interactive loop is done, restore collectd's
1087    *    SIGINT handler.
1088    * 4. Raise SIGINT for a clean shutdown. The signal is sent to
1089    *    the main thread to ensure it wakes up the main interval
1090    *    sleep so that collectd shuts down immediately not in 10
1091    *    seconds.
1092    *
1093    * This will make sure that SIGINT won't kill collectd but
1094    * still interrupt syscalls like sleep and pause. */
1095
1096   if (PyImport_ImportModule("readline") == NULL) {
1097     /* This interactive session will suck. */
1098     cpy_log_exception("interactive session init");
1099   }
1100   cur_sig = PyOS_setsig(SIGINT, python_sigint_handler);
1101   PyOS_AfterFork();
1102   PyEval_InitThreads();
1103   close(*(int *)pipefd);
1104   PyRun_InteractiveLoop(stdin, "<stdin>");
1105   PyOS_setsig(SIGINT, cur_sig);
1106   PyErr_Print();
1107   state = PyEval_SaveThread();
1108   NOTICE("python: Interactive interpreter exited, stopping collectd ...");
1109   pthread_kill(main_thread, SIGINT);
1110   return NULL;
1111 }
1112
1113 static int cpy_init(void) {
1114   PyObject *ret;
1115   int pipefd[2];
1116   char buf;
1117   static pthread_t thread;
1118
1119   if (!Py_IsInitialized()) {
1120     WARNING("python: Plugin loaded but not configured.");
1121     plugin_unregister_shutdown("python");
1122     Py_Finalize();
1123     return 0;
1124   }
1125   main_thread = pthread_self();
1126   if (do_interactive) {
1127     if (pipe(pipefd)) {
1128       ERROR("python: Unable to create pipe.");
1129       return 1;
1130     }
1131     if (plugin_thread_create(&thread, NULL, cpy_interactive, pipefd + 1,
1132                              "python interpreter")) {
1133       ERROR("python: Error creating thread for interactive interpreter.");
1134     }
1135     if (read(pipefd[0], &buf, 1))
1136       ;
1137     (void)close(pipefd[0]);
1138   } else {
1139     PyEval_InitThreads();
1140     state = PyEval_SaveThread();
1141   }
1142   CPY_LOCK_THREADS
1143   for (cpy_callback_t *c = cpy_init_callbacks; c; c = c->next) {
1144     ret = PyObject_CallFunctionObjArgs(c->callback, c->data,
1145                                        (void *)0); /* New reference. */
1146     if (ret == NULL)
1147       cpy_log_exception("init callback");
1148     else
1149       Py_DECREF(ret);
1150   }
1151   CPY_RELEASE_THREADS
1152
1153   return 0;
1154 }
1155
1156 static PyObject *cpy_oconfig_to_pyconfig(oconfig_item_t *ci, PyObject *parent) {
1157   PyObject *item, *values, *children, *tmp;
1158
1159   if (parent == NULL)
1160     parent = Py_None;
1161
1162   values = PyTuple_New(ci->values_num); /* New reference. */
1163   for (int i = 0; i < ci->values_num; ++i) {
1164     if (ci->values[i].type == OCONFIG_TYPE_STRING) {
1165       PyTuple_SET_ITEM(values, i, cpy_string_to_unicode_or_bytes(
1166                                       ci->values[i].value.string));
1167     } else if (ci->values[i].type == OCONFIG_TYPE_NUMBER) {
1168       PyTuple_SET_ITEM(values, i,
1169                        PyFloat_FromDouble(ci->values[i].value.number));
1170     } else if (ci->values[i].type == OCONFIG_TYPE_BOOLEAN) {
1171       PyTuple_SET_ITEM(values, i, PyBool_FromLong(ci->values[i].value.boolean));
1172     }
1173   }
1174
1175   tmp = cpy_string_to_unicode_or_bytes(ci->key);
1176   item = PyObject_CallFunction((void *)&ConfigType, "NONO", tmp, parent, values,
1177                                Py_None);
1178   if (item == NULL)
1179     return NULL;
1180   children = PyTuple_New(ci->children_num); /* New reference. */
1181   for (int i = 0; i < ci->children_num; ++i) {
1182     PyTuple_SET_ITEM(children, i,
1183                      cpy_oconfig_to_pyconfig(ci->children + i, item));
1184   }
1185   tmp = ((Config *)item)->children;
1186   ((Config *)item)->children = children;
1187   Py_XDECREF(tmp);
1188   return item;
1189 }
1190
1191 #ifdef IS_PY3K
1192 static struct PyModuleDef collectdmodule = {
1193     PyModuleDef_HEAD_INIT, "collectd",  /* name of module */
1194     "The python interface to collectd", /* module documentation, may be NULL */
1195     -1, cpy_methods};
1196
1197 PyMODINIT_FUNC PyInit_collectd(void) {
1198   return PyModule_Create(&collectdmodule);
1199 }
1200 #endif
1201
1202 static int cpy_init_python(void) {
1203   PyOS_sighandler_t cur_sig;
1204   PyObject *sys, *errordict;
1205   PyObject *module;
1206
1207 #ifdef IS_PY3K
1208   wchar_t *argv = L"";
1209   /* Add a builtin module, before Py_Initialize */
1210   PyImport_AppendInittab("collectd", PyInit_collectd);
1211 #else
1212   char *argv = "";
1213 #endif
1214
1215   /* Chances are the current signal handler is already SIG_DFL, but let's make
1216    * sure. */
1217   cur_sig = PyOS_setsig(SIGINT, SIG_DFL);
1218   Py_Initialize();
1219   python_sigint_handler = PyOS_setsig(SIGINT, cur_sig);
1220
1221   PyType_Ready(&ConfigType);
1222   PyType_Ready(&PluginDataType);
1223   ValuesType.tp_base = &PluginDataType;
1224   PyType_Ready(&ValuesType);
1225   NotificationType.tp_base = &PluginDataType;
1226   PyType_Ready(&NotificationType);
1227   SignedType.tp_base = &PyLong_Type;
1228   PyType_Ready(&SignedType);
1229   UnsignedType.tp_base = &PyLong_Type;
1230   PyType_Ready(&UnsignedType);
1231   errordict = PyDict_New();
1232   PyDict_SetItemString(errordict, "__doc__", 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", CollectdError); /* Steals a reference. */
1265   PyModule_AddIntConstant(module, "LOG_DEBUG", LOG_DEBUG);
1266   PyModule_AddIntConstant(module, "LOG_INFO", LOG_INFO);
1267   PyModule_AddIntConstant(module, "LOG_NOTICE", LOG_NOTICE);
1268   PyModule_AddIntConstant(module, "LOG_WARNING", LOG_WARNING);
1269   PyModule_AddIntConstant(module, "LOG_ERROR", LOG_ERR);
1270   PyModule_AddIntConstant(module, "NOTIF_FAILURE", NOTIF_FAILURE);
1271   PyModule_AddIntConstant(module, "NOTIF_WARNING", NOTIF_WARNING);
1272   PyModule_AddIntConstant(module, "NOTIF_OKAY", NOTIF_OKAY);
1273   PyModule_AddStringConstant(module, "DS_TYPE_COUNTER",
1274                              DS_TYPE_TO_STRING(DS_TYPE_COUNTER));
1275   PyModule_AddStringConstant(module, "DS_TYPE_GAUGE",
1276                              DS_TYPE_TO_STRING(DS_TYPE_GAUGE));
1277   PyModule_AddStringConstant(module, "DS_TYPE_DERIVE",
1278                              DS_TYPE_TO_STRING(DS_TYPE_DERIVE));
1279   PyModule_AddStringConstant(module, "DS_TYPE_ABSOLUTE",
1280                              DS_TYPE_TO_STRING(DS_TYPE_ABSOLUTE));
1281   return 0;
1282 }
1283
1284 static int cpy_config(oconfig_item_t *ci) {
1285   PyObject *tb;
1286   int status = 0;
1287
1288   /* Ok in theory we shouldn't do initialization at this point
1289    * but we have to. In order to give python scripts a chance
1290    * to register a config callback we need to be able to execute
1291    * python code during the config callback so we have to start
1292    * the interpreter here. */
1293   /* Do *not* use the python "thread" module at this point! */
1294
1295   if (!Py_IsInitialized() && cpy_init_python())
1296     return 1;
1297
1298   for (int i = 0; i < ci->children_num; ++i) {
1299     oconfig_item_t *item = ci->children + i;
1300
1301     if (strcasecmp(item->key, "Interactive") == 0) {
1302       if (cf_util_get_boolean(item, &do_interactive) != 0) {
1303         status = 1;
1304         continue;
1305       }
1306     } else if (strcasecmp(item->key, "Encoding") == 0) {
1307       char *encoding = NULL;
1308       if (cf_util_get_string(item, &encoding) != 0) {
1309         status = 1;
1310         continue;
1311       }
1312 #ifdef IS_PY3K
1313       ERROR("python: \"Encoding\" was used in the config file but Python3 was "
1314             "used, which does not support changing encodings");
1315       status = 1;
1316       sfree(encoding);
1317       continue;
1318 #else
1319       /* Why is this even necessary? And undocumented? */
1320       if (PyUnicode_SetDefaultEncoding(encoding)) {
1321         cpy_log_exception("setting default encoding");
1322         status = 1;
1323       }
1324 #endif
1325       sfree(encoding);
1326     } else if (strcasecmp(item->key, "LogTraces") == 0) {
1327       _Bool log_traces;
1328       if (cf_util_get_boolean(item, &log_traces) != 0) {
1329         status = 1;
1330         continue;
1331       }
1332       if (!log_traces) {
1333         Py_XDECREF(cpy_format_exception);
1334         cpy_format_exception = NULL;
1335         continue;
1336       }
1337       if (cpy_format_exception)
1338         continue;
1339       tb = PyImport_ImportModule("traceback"); /* New reference. */
1340       if (tb == NULL) {
1341         cpy_log_exception("python initialization");
1342         status = 1;
1343         continue;
1344       }
1345       cpy_format_exception =
1346           PyObject_GetAttrString(tb, "format_exception"); /* New reference. */
1347       Py_DECREF(tb);
1348       if (cpy_format_exception == NULL) {
1349         cpy_log_exception("python initialization");
1350         status = 1;
1351       }
1352     } else if (strcasecmp(item->key, "ModulePath") == 0) {
1353       char *dir = NULL;
1354       PyObject *dir_object;
1355
1356       if (cf_util_get_string(item, &dir) != 0) {
1357         status = 1;
1358         continue;
1359       }
1360       dir_object = cpy_string_to_unicode_or_bytes(dir); /* New reference. */
1361       if (dir_object == NULL) {
1362         ERROR("python plugin: Unable to convert \"%s\" to "
1363               "a python object.",
1364               dir);
1365         free(dir);
1366         cpy_log_exception("python initialization");
1367         status = 1;
1368         continue;
1369       }
1370       if (PyList_Insert(sys_path, 0, dir_object) != 0) {
1371         ERROR("python plugin: Unable to prepend \"%s\" to "
1372               "python module path.",
1373               dir);
1374         cpy_log_exception("python initialization");
1375         status = 1;
1376       }
1377       Py_DECREF(dir_object);
1378       free(dir);
1379     } else if (strcasecmp(item->key, "Import") == 0) {
1380       char *module_name = NULL;
1381       PyObject *module;
1382
1383       if (cf_util_get_string(item, &module_name) != 0) {
1384         status = 1;
1385         continue;
1386       }
1387       module = PyImport_ImportModule(module_name); /* New reference. */
1388       if (module == NULL) {
1389         ERROR("python plugin: Error importing module \"%s\".", module_name);
1390         cpy_log_exception("importing module");
1391         status = 1;
1392       }
1393       free(module_name);
1394       Py_XDECREF(module);
1395     } else if (strcasecmp(item->key, "Module") == 0) {
1396       char *name = NULL;
1397       cpy_callback_t *c;
1398       PyObject *ret;
1399
1400       if (cf_util_get_string(item, &name) != 0) {
1401         status = 1;
1402         continue;
1403       }
1404       for (c = cpy_config_callbacks; c; c = c->next) {
1405         if (strcasecmp(c->name + 7, name) == 0)
1406           break;
1407       }
1408       if (c == NULL) {
1409         WARNING("python plugin: Found a configuration for the \"%s\" plugin, "
1410                 "but the plugin isn't loaded or didn't register "
1411                 "a configuration callback.",
1412                 name);
1413         free(name);
1414         continue;
1415       }
1416       free(name);
1417       if (c->data == NULL)
1418         ret = PyObject_CallFunction(
1419             c->callback, "N",
1420             cpy_oconfig_to_pyconfig(item, NULL)); /* New reference. */
1421       else
1422         ret = PyObject_CallFunction(c->callback, "NO",
1423                                     cpy_oconfig_to_pyconfig(item, NULL),
1424                                     c->data); /* New reference. */
1425       if (ret == NULL) {
1426         cpy_log_exception("loading module");
1427         status = 1;
1428       } else
1429         Py_DECREF(ret);
1430     } else {
1431       ERROR("python plugin: Unknown config key \"%s\".", item->key);
1432       status = 1;
1433     }
1434   }
1435   return status;
1436 }
1437
1438 void module_register(void) {
1439   plugin_register_complex_config("python", cpy_config);
1440   plugin_register_init("python", cpy_init);
1441   plugin_register_shutdown("python", cpy_shutdown);
1442 }