Merge branch 'collectd-5.6'
[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                         ERROR("python: Error creating thread for interactive interpreter.");
1025                 }
1026                 if(read(pipefd[0], &buf, 1))
1027                         ;
1028                 (void)close(pipefd[0]);
1029         } else {
1030                 PyEval_InitThreads();
1031                 state = PyEval_SaveThread();
1032         }
1033         CPY_LOCK_THREADS
1034         for (cpy_callback_t *c = cpy_init_callbacks; c; c = c->next) {
1035                 ret = PyObject_CallFunctionObjArgs(c->callback, c->data, (void *) 0); /* New reference. */
1036                 if (ret == NULL)
1037                         cpy_log_exception("init callback");
1038                 else
1039                         Py_DECREF(ret);
1040         }
1041         CPY_RELEASE_THREADS
1042
1043         return 0;
1044 }
1045
1046 static PyObject *cpy_oconfig_to_pyconfig(oconfig_item_t *ci, PyObject *parent) {
1047         PyObject *item, *values, *children, *tmp;
1048
1049         if (parent == NULL)
1050                 parent = Py_None;
1051
1052         values = PyTuple_New(ci->values_num); /* New reference. */
1053         for (int i = 0; i < ci->values_num; ++i) {
1054                 if (ci->values[i].type == OCONFIG_TYPE_STRING) {
1055                         PyTuple_SET_ITEM(values, i, cpy_string_to_unicode_or_bytes(ci->values[i].value.string));
1056                 } else if (ci->values[i].type == OCONFIG_TYPE_NUMBER) {
1057                         PyTuple_SET_ITEM(values, i, PyFloat_FromDouble(ci->values[i].value.number));
1058                 } else if (ci->values[i].type == OCONFIG_TYPE_BOOLEAN) {
1059                         PyTuple_SET_ITEM(values, i, PyBool_FromLong(ci->values[i].value.boolean));
1060                 }
1061         }
1062
1063         tmp = cpy_string_to_unicode_or_bytes(ci->key);
1064         item = PyObject_CallFunction((void *) &ConfigType, "NONO", tmp, parent, values, Py_None);
1065         if (item == NULL)
1066                 return NULL;
1067         children = PyTuple_New(ci->children_num); /* New reference. */
1068         for (int i = 0; i < ci->children_num; ++i) {
1069                 PyTuple_SET_ITEM(children, i, cpy_oconfig_to_pyconfig(ci->children + i, item));
1070         }
1071         tmp = ((Config *) item)->children;
1072         ((Config *) item)->children = children;
1073         Py_XDECREF(tmp);
1074         return item;
1075 }
1076
1077 #ifdef IS_PY3K
1078 static struct PyModuleDef collectdmodule = {
1079         PyModuleDef_HEAD_INIT,
1080         "collectd",   /* name of module */
1081         "The python interface to collectd", /* module documentation, may be NULL */
1082         -1,
1083         cpy_methods
1084 };
1085
1086 PyMODINIT_FUNC PyInit_collectd(void) {
1087         return PyModule_Create(&collectdmodule);
1088 }
1089 #endif
1090
1091 static int cpy_init_python(void) {
1092         PyOS_sighandler_t cur_sig;
1093         PyObject *sys;
1094         PyObject *module;
1095
1096 #ifdef IS_PY3K
1097         wchar_t *argv = L"";
1098         /* Add a builtin module, before Py_Initialize */
1099         PyImport_AppendInittab("collectd", PyInit_collectd);
1100 #else
1101         char *argv = "";
1102 #endif
1103
1104         /* Chances are the current signal handler is already SIG_DFL, but let's make sure. */
1105         cur_sig = PyOS_setsig(SIGINT, SIG_DFL);
1106         Py_Initialize();
1107         python_sigint_handler = PyOS_setsig(SIGINT, cur_sig);
1108
1109         PyType_Ready(&ConfigType);
1110         PyType_Ready(&PluginDataType);
1111         ValuesType.tp_base = &PluginDataType;
1112         PyType_Ready(&ValuesType);
1113         NotificationType.tp_base = &PluginDataType;
1114         PyType_Ready(&NotificationType);
1115         SignedType.tp_base = &PyLong_Type;
1116         PyType_Ready(&SignedType);
1117         UnsignedType.tp_base = &PyLong_Type;
1118         PyType_Ready(&UnsignedType);
1119         sys = PyImport_ImportModule("sys"); /* New reference. */
1120         if (sys == NULL) {
1121                 cpy_log_exception("python initialization");
1122                 return 1;
1123         }
1124         sys_path = PyObject_GetAttrString(sys, "path"); /* New reference. */
1125         Py_DECREF(sys);
1126         if (sys_path == NULL) {
1127                 cpy_log_exception("python initialization");
1128                 return 1;
1129         }
1130         PySys_SetArgv(1, &argv);
1131         PyList_SetSlice(sys_path, 0, 1, NULL);
1132
1133 #ifdef IS_PY3K
1134         module = PyImport_ImportModule("collectd");
1135 #else
1136         module = Py_InitModule("collectd", cpy_methods); /* Borrowed reference. */
1137 #endif
1138         PyModule_AddObject(module, "Config", (void *) &ConfigType); /* Steals a reference. */
1139         PyModule_AddObject(module, "Values", (void *) &ValuesType); /* Steals a reference. */
1140         PyModule_AddObject(module, "Notification", (void *) &NotificationType); /* Steals a reference. */
1141         PyModule_AddObject(module, "Signed", (void *) &SignedType); /* Steals a reference. */
1142         PyModule_AddObject(module, "Unsigned", (void *) &UnsignedType); /* Steals a reference. */
1143         PyModule_AddIntConstant(module, "LOG_DEBUG", LOG_DEBUG);
1144         PyModule_AddIntConstant(module, "LOG_INFO", LOG_INFO);
1145         PyModule_AddIntConstant(module, "LOG_NOTICE", LOG_NOTICE);
1146         PyModule_AddIntConstant(module, "LOG_WARNING", LOG_WARNING);
1147         PyModule_AddIntConstant(module, "LOG_ERROR", LOG_ERR);
1148         PyModule_AddIntConstant(module, "NOTIF_FAILURE", NOTIF_FAILURE);
1149         PyModule_AddIntConstant(module, "NOTIF_WARNING", NOTIF_WARNING);
1150         PyModule_AddIntConstant(module, "NOTIF_OKAY", NOTIF_OKAY);
1151         PyModule_AddStringConstant(module, "DS_TYPE_COUNTER", DS_TYPE_TO_STRING(DS_TYPE_COUNTER));
1152         PyModule_AddStringConstant(module, "DS_TYPE_GAUGE", DS_TYPE_TO_STRING(DS_TYPE_GAUGE));
1153         PyModule_AddStringConstant(module, "DS_TYPE_DERIVE", DS_TYPE_TO_STRING(DS_TYPE_DERIVE));
1154         PyModule_AddStringConstant(module, "DS_TYPE_ABSOLUTE", DS_TYPE_TO_STRING(DS_TYPE_ABSOLUTE));
1155         return 0;
1156 }
1157
1158 static int cpy_config(oconfig_item_t *ci) {
1159         PyObject *tb;
1160         int status = 0;
1161
1162         /* Ok in theory we shouldn't do initialization at this point
1163          * but we have to. In order to give python scripts a chance
1164          * to register a config callback we need to be able to execute
1165          * python code during the config callback so we have to start
1166          * the interpreter here. */
1167         /* Do *not* use the python "thread" module at this point! */
1168
1169         if (!Py_IsInitialized() && cpy_init_python()) return 1;
1170
1171         for (int i = 0; i < ci->children_num; ++i) {
1172                 oconfig_item_t *item = ci->children + i;
1173
1174                 if (strcasecmp(item->key, "Interactive") == 0) {
1175                         if (cf_util_get_boolean(item, &do_interactive) != 0) {
1176                                 status = 1;
1177                                 continue;
1178                         }
1179                 } else if (strcasecmp(item->key, "Encoding") == 0) {
1180                         char *encoding = NULL;
1181                         if (cf_util_get_string(item, &encoding) != 0) {
1182                                 status = 1;
1183                                 continue;
1184                         }
1185 #ifdef IS_PY3K
1186                         ERROR("python: \"Encoding\" was used in the config file but Python3 was used, which does not support changing encodings");
1187                         status = 1;
1188                         sfree(encoding);
1189                         continue;
1190 #else
1191                         /* Why is this even necessary? And undocumented? */
1192                         if (PyUnicode_SetDefaultEncoding(encoding)) {
1193                                 cpy_log_exception("setting default encoding");
1194                                 status = 1;
1195                         }
1196 #endif
1197                         sfree(encoding);
1198                 } else if (strcasecmp(item->key, "LogTraces") == 0) {
1199                         _Bool log_traces;
1200                         if (cf_util_get_boolean(item, &log_traces) != 0) {
1201                                 status = 1;
1202                                 continue;
1203                         }
1204                         if (!log_traces) {
1205                                 Py_XDECREF(cpy_format_exception);
1206                                 cpy_format_exception = NULL;
1207                                 continue;
1208                         }
1209                         if (cpy_format_exception)
1210                                 continue;
1211                         tb = PyImport_ImportModule("traceback"); /* New reference. */
1212                         if (tb == NULL) {
1213                                 cpy_log_exception("python initialization");
1214                                 status = 1;
1215                                 continue;
1216                         }
1217                         cpy_format_exception = PyObject_GetAttrString(tb, "format_exception"); /* New reference. */
1218                         Py_DECREF(tb);
1219                         if (cpy_format_exception == NULL) {
1220                                 cpy_log_exception("python initialization");
1221                                 status = 1;
1222                         }
1223                 } else if (strcasecmp(item->key, "ModulePath") == 0) {
1224                         char *dir = NULL;
1225                         PyObject *dir_object;
1226
1227                         if (cf_util_get_string(item, &dir) != 0) {
1228                                 status = 1;
1229                                 continue;
1230                         }
1231                         dir_object = cpy_string_to_unicode_or_bytes(dir); /* New reference. */
1232                         if (dir_object == NULL) {
1233                                 ERROR("python plugin: Unable to convert \"%s\" to "
1234                                       "a python object.", dir);
1235                                 free(dir);
1236                                 cpy_log_exception("python initialization");
1237                                 status = 1;
1238                                 continue;
1239                         }
1240                         if (PyList_Insert(sys_path, 0, dir_object) != 0) {
1241                                 ERROR("python plugin: Unable to prepend \"%s\" to "
1242                                       "python module path.", dir);
1243                                 cpy_log_exception("python initialization");
1244                                 status = 1;
1245                         }
1246                         Py_DECREF(dir_object);
1247                         free(dir);
1248                 } else if (strcasecmp(item->key, "Import") == 0) {
1249                         char *module_name = NULL;
1250                         PyObject *module;
1251
1252                         if (cf_util_get_string(item, &module_name) != 0) {
1253                                 status = 1;
1254                                 continue;
1255                         }
1256                         module = PyImport_ImportModule(module_name); /* New reference. */
1257                         if (module == NULL) {
1258                                 ERROR("python plugin: Error importing module \"%s\".", module_name);
1259                                 cpy_log_exception("importing module");
1260                                 status = 1;
1261                         }
1262                         free(module_name);
1263                         Py_XDECREF(module);
1264                 } else if (strcasecmp(item->key, "Module") == 0) {
1265                         char *name = NULL;
1266                         cpy_callback_t *c;
1267                         PyObject *ret;
1268
1269                         if (cf_util_get_string(item, &name) != 0) {
1270                                 status = 1;
1271                                 continue;
1272                         }
1273                         for (c = cpy_config_callbacks; c; c = c->next) {
1274                                 if (strcasecmp(c->name + 7, name) == 0)
1275                                         break;
1276                         }
1277                         if (c == NULL) {
1278                                 WARNING("python plugin: Found a configuration for the \"%s\" plugin, "
1279                                         "but the plugin isn't loaded or didn't register "
1280                                         "a configuration callback.", name);
1281                                 free(name);
1282                                 continue;
1283                         }
1284                         free(name);
1285                         if (c->data == NULL)
1286                                 ret = PyObject_CallFunction(c->callback, "N",
1287                                         cpy_oconfig_to_pyconfig(item, NULL)); /* New reference. */
1288                         else
1289                                 ret = PyObject_CallFunction(c->callback, "NO",
1290                                         cpy_oconfig_to_pyconfig(item, NULL), c->data); /* New reference. */
1291                         if (ret == NULL) {
1292                                 cpy_log_exception("loading module");
1293                                 status = 1;
1294                         } else
1295                                 Py_DECREF(ret);
1296                 } else {
1297                         ERROR("python plugin: Unknown config key \"%s\".", item->key);
1298                         status = 1;
1299                 }
1300         }
1301         return (status);
1302 }
1303
1304 void module_register(void) {
1305         plugin_register_complex_config("python", cpy_config);
1306         plugin_register_init("python", cpy_init);
1307         plugin_register_shutdown("python", cpy_shutdown);
1308 }