Add sys.argv. Not too many programs consider the possibility that it might not exist...
[collectd.git] / src / python.c
index 006aecf..16de81d 100644 (file)
@@ -1,3 +1,29 @@
+/**
+ * collectd - src/python.c
+ * Copyright (C) 2009  Sven Trenkel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *   Sven Trenkel <collectd at semidefinite.de>  
+ **/
+
 #include <Python.h>
 #include <structmember.h>
 
@@ -276,7 +302,6 @@ static void cpy_log_exception(const char *context) {
                
                line = PyList_GET_ITEM(list, i); /* Borrowed reference. */
                s = strdup(PyString_AsString(line));
-               Py_DECREF(line);
                if (s[strlen(s) - 1] == '\n')
                        s[strlen(s) - 1] = 0;
                Py_BEGIN_ALLOW_THREADS
@@ -343,14 +368,17 @@ static int cpy_write_callback(const data_set_t *ds, const value_list_t *value_li
                        }
                        if (PyErr_Occurred() != NULL) {
                                cpy_log_exception("value building for write callback");
+                               Py_DECREF(list);
                                CPY_RETURN_FROM_THREADS 0;
                        }
                }
-               v = PyObject_CallFunction((void *) &ValuesType, "sOssssdi", value_list->type, list,
-                               value_list->plugin_instance, value_list->type_instance, value_list->plugin,
-                               value_list->host, (double) value_list->time, value_list->interval);
+               v = PyObject_CallFunction((void *) &ValuesType, "sOssssdi", value_list->type,
+                               list, value_list->plugin_instance, value_list->type_instance,
+                               value_list->plugin, value_list->host, (double) value_list->time,
+                               value_list->interval); /* New reference. */
                Py_DECREF(list);
                ret = PyObject_CallFunctionObjArgs(c->callback, v, c->data, (void *) 0); /* New reference. */
+               Py_XDECREF(v);
                if (ret == NULL) {
                        cpy_log_exception("write callback");
                } else {
@@ -367,8 +395,9 @@ static int cpy_notification_callback(const notification_t *notification, user_da
        CPY_LOCK_THREADS
                n = PyObject_CallFunction((void *) &NotificationType, "ssssssdi", notification->type, notification->message,
                                notification->plugin_instance, notification->type_instance, notification->plugin,
-                               notification->host, (double) notification->time, notification->severity);
+                               notification->host, (double) notification->time, notification->severity); /* New reference. */
                ret = PyObject_CallFunctionObjArgs(c->callback, n, c->data, (void *) 0); /* New reference. */
+               Py_XDECREF(n);
                if (ret == NULL) {
                        cpy_log_exception("notification callback");
                } else {
@@ -803,6 +832,11 @@ static int cpy_init(void) {
        static pthread_t thread;
        sigset_t sigset;
        
+       if (!Py_IsInitialized()) {
+               WARNING("python: Plugin loaded but not configured.");
+               plugin_unregister_shutdown("python");
+               return 0;
+       }
        PyEval_InitThreads();
        /* Now it's finally OK to use python threads. */
        for (c = cpy_init_callbacks; c; c = c->next) {
@@ -858,6 +892,7 @@ static PyObject *cpy_oconfig_to_pyconfig(oconfig_item_t *ci, PyObject *parent) {
 
 static int cpy_config(oconfig_item_t *ci) {
        int i;
+       char *argv = "";
        PyObject *sys, *tb;
        PyObject *sys_path;
        PyObject *module;
@@ -887,6 +922,9 @@ static int cpy_config(oconfig_item_t *ci) {
                cpy_log_exception("python initialization");
                return 1;
        }
+       PySys_SetArgv(1, &argv);
+       PyList_SetSlice(sys_path, 0, 1, NULL);
+
        module = Py_InitModule("collectd", cpy_methods); /* Borrowed reference. */
        PyModule_AddObject(module, "Config", (void *) &ConfigType); /* Steals a reference. */
        PyModule_AddObject(module, "Values", (void *) &ValuesType); /* Steals a reference. */