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