Merge remote-tracking branch 'octo/master'
authorSven Trenkel <collectd@semidefinite.de>
Sun, 16 Jul 2017 22:49:59 +0000 (22:49 +0000)
committerSven Trenkel <collectd@semidefinite.de>
Sun, 16 Jul 2017 22:49:59 +0000 (22:49 +0000)
1  2 
src/python.c

diff --combined src/python.c
@@@ -233,12 -233,6 +233,12 @@@ static char reg_shutdown_doc[] 
      "The callback function will be called with no parameters except for\n"
      "    data if it was supplied.";
  
 +static char CollectdError_doc[] =
 +    "Basic exception for collectd Python scripts.\n"
 +    "\n"
 +    "Throwing this exception will not cause a stacktrace to be logged, \n"
 +    "even if LogTraces is enabled in the config.";
 +
  static pthread_t main_thread;
  static PyOS_sighandler_t python_sigint_handler;
  static _Bool do_interactive = 0;
  
  static PyThreadState *state;
  
 -static PyObject *sys_path, *cpy_format_exception;
 +static PyObject *sys_path, *cpy_format_exception, *CollectdError;
  
  static cpy_callback_t *cpy_config_callbacks;
  static cpy_callback_t *cpy_init_callbacks;
@@@ -306,7 -300,7 +306,7 @@@ static void cpy_build_name(char *buf, s
  }
  
  void cpy_log_exception(const char *context) {
 -  int l = 0;
 +  int l = 0, collectd_error;
    const char *typename = NULL, *message = NULL;
    PyObject *type, *value, *traceback, *tn, *m, *list;
  
    PyErr_NormalizeException(&type, &value, &traceback);
    if (type == NULL)
      return;
 +  collectd_error = PyErr_GivenExceptionMatches(value, CollectdError);
    tn = PyObject_GetAttrString(type, "__name__"); /* New reference. */
    m = PyObject_Str(value);                       /* New reference. */
    if (tn != NULL)
      typename = "NamelessException";
    if (message == NULL)
      message = "N/A";
 -  Py_BEGIN_ALLOW_THREADS ERROR("Unhandled python exception in %s: %s: %s",
 -                               context, typename, message);
 -  Py_END_ALLOW_THREADS Py_XDECREF(tn);
 +  Py_BEGIN_ALLOW_THREADS
 +  if (collectd_error) {
 +    WARNING("%s in %s: %s", typename, context, message);
 +  } else {
 +    ERROR("Unhandled python exception in %s: %s: %s",
 +          context, typename, message);
 +  }
 +  Py_END_ALLOW_THREADS
 +  Py_XDECREF(tn);
    Py_XDECREF(m);
 -  if (!cpy_format_exception || !traceback) {
 +  if (!cpy_format_exception || !traceback || collectd_error) {
      PyErr_Clear();
      Py_DECREF(type);
      Py_XDECREF(value);
      if (cpy[strlen(cpy) - 1] == '\n')
        cpy[strlen(cpy) - 1] = 0;
  
 -    Py_BEGIN_ALLOW_THREADS ERROR("%s", cpy);
 +    Py_BEGIN_ALLOW_THREADS
 +    ERROR("%s", cpy);
      Py_END_ALLOW_THREADS
  
 -        free(cpy);
 +    free(cpy);
    }
  
    Py_XDECREF(list);
@@@ -424,10 -410,9 +424,10 @@@ static int cpy_write_callback(const dat
        PyList_SetItem(
            list, i, PyLong_FromUnsignedLongLong(value_list->values[i].absolute));
      } else {
 -      Py_BEGIN_ALLOW_THREADS ERROR("cpy_write_callback: Unknown value type %d.",
 -                                   ds->ds[i].type);
 -      Py_END_ALLOW_THREADS Py_DECREF(list);
 +      Py_BEGIN_ALLOW_THREADS
 +      ERROR("cpy_write_callback: Unknown value type %d.", ds->ds[i].type);
 +      Py_END_ALLOW_THREADS
 +      Py_DECREF(list);
        CPY_RETURN_FROM_THREADS 0;
      }
      if (PyErr_Occurred() != NULL) {
@@@ -683,10 -668,8 +683,10 @@@ static PyObject *cpy_flush(PyObject *se
    if (PyArg_ParseTupleAndKeywords(args, kwds, "|etiet", kwlist, NULL, &plugin,
                                    &timeout, NULL, &identifier) == 0)
      return NULL;
 -  Py_BEGIN_ALLOW_THREADS plugin_flush(plugin, timeout, identifier);
 -  Py_END_ALLOW_THREADS PyMem_Free(plugin);
 +  Py_BEGIN_ALLOW_THREADS
 +  plugin_flush(plugin, timeout, identifier);
 +  Py_END_ALLOW_THREADS
 +  PyMem_Free(plugin);
    PyMem_Free(identifier);
    Py_RETURN_NONE;
  }
@@@ -801,8 -784,8 +801,8 @@@ static PyObject *cpy_register_write(PyO
  static PyObject *cpy_register_notification(PyObject *self, PyObject *args,
                                             PyObject *kwds) {
    return cpy_register_generic_userdata((void *)plugin_register_notification,
-                                        (void *)cpy_notification_callback,
-                                        args, kwds);
+                                        (void *)cpy_notification_callback, args,
+                                        kwds);
  }
  
  static PyObject *cpy_register_flush(PyObject *self, PyObject *args,
@@@ -820,10 -803,8 +820,10 @@@ static PyObject *cpy_error(PyObject *se
    char *text;
    if (PyArg_ParseTuple(args, "et", NULL, &text) == 0)
      return NULL;
 -  Py_BEGIN_ALLOW_THREADS plugin_log(LOG_ERR, "%s", text);
 -  Py_END_ALLOW_THREADS PyMem_Free(text);
 +  Py_BEGIN_ALLOW_THREADS
 +  plugin_log(LOG_ERR, "%s", text);
 +  Py_END_ALLOW_THREADS
 +  PyMem_Free(text);
    Py_RETURN_NONE;
  }
  
@@@ -831,10 -812,8 +831,10 @@@ static PyObject *cpy_warning(PyObject *
    char *text;
    if (PyArg_ParseTuple(args, "et", NULL, &text) == 0)
      return NULL;
 -  Py_BEGIN_ALLOW_THREADS plugin_log(LOG_WARNING, "%s", text);
 -  Py_END_ALLOW_THREADS PyMem_Free(text);
 +  Py_BEGIN_ALLOW_THREADS
 +  plugin_log(LOG_WARNING, "%s", text);
 +  Py_END_ALLOW_THREADS
 +  PyMem_Free(text);
    Py_RETURN_NONE;
  }
  
@@@ -842,10 -821,8 +842,10 @@@ static PyObject *cpy_notice(PyObject *s
    char *text;
    if (PyArg_ParseTuple(args, "et", NULL, &text) == 0)
      return NULL;
 -  Py_BEGIN_ALLOW_THREADS plugin_log(LOG_NOTICE, "%s", text);
 -  Py_END_ALLOW_THREADS PyMem_Free(text);
 +  Py_BEGIN_ALLOW_THREADS
 +  plugin_log(LOG_NOTICE, "%s", text);
 +  Py_END_ALLOW_THREADS
 +  PyMem_Free(text);
    Py_RETURN_NONE;
  }
  
@@@ -853,10 -830,8 +853,10 @@@ static PyObject *cpy_info(PyObject *sel
    char *text;
    if (PyArg_ParseTuple(args, "et", NULL, &text) == 0)
      return NULL;
 -  Py_BEGIN_ALLOW_THREADS plugin_log(LOG_INFO, "%s", text);
 -  Py_END_ALLOW_THREADS PyMem_Free(text);
 +  Py_BEGIN_ALLOW_THREADS
 +  plugin_log(LOG_INFO, "%s", text);
 +  Py_END_ALLOW_THREADS
 +  PyMem_Free(text);
    Py_RETURN_NONE;
  }
  
@@@ -865,10 -840,8 +865,10 @@@ static PyObject *cpy_debug(PyObject *se
    char *text;
    if (PyArg_ParseTuple(args, "et", NULL, &text) == 0)
      return NULL;
 -  Py_BEGIN_ALLOW_THREADS plugin_log(LOG_DEBUG, "%s", text);
 -  Py_END_ALLOW_THREADS PyMem_Free(text);
 +  Py_BEGIN_ALLOW_THREADS
 +  plugin_log(LOG_DEBUG, "%s", text);
 +  Py_END_ALLOW_THREADS
 +  PyMem_Free(text);
  #endif
    Py_RETURN_NONE;
  }
@@@ -971,8 -944,7 +971,7 @@@ static PyObject *cpy_unregister_read(Py
  }
  
  static PyObject *cpy_unregister_write(PyObject *self, PyObject *arg) {
-   return cpy_unregister_generic_userdata(plugin_unregister_write, arg,
-                                          "write");
+   return cpy_unregister_generic_userdata(plugin_unregister_write, arg, "write");
  }
  
  static PyObject *cpy_unregister_notification(PyObject *self, PyObject *arg) {
  }
  
  static PyObject *cpy_unregister_flush(PyObject *self, PyObject *arg) {
-   return cpy_unregister_generic_userdata(plugin_unregister_flush, arg,
-                                          "flush");
+   return cpy_unregister_generic_userdata(plugin_unregister_flush, arg, "flush");
  }
  
  static PyObject *cpy_unregister_shutdown(PyObject *self, PyObject *arg) {
@@@ -1052,14 -1023,13 +1050,14 @@@ static int cpy_shutdown(void) 
    }
    PyErr_Print();
  
 -  Py_BEGIN_ALLOW_THREADS cpy_unregister_list(&cpy_config_callbacks);
 +  Py_BEGIN_ALLOW_THREADS
 +  cpy_unregister_list(&cpy_config_callbacks);
    cpy_unregister_list(&cpy_init_callbacks);
    cpy_unregister_list(&cpy_shutdown_callbacks);
    cpy_shutdown_triggered = 1;
    Py_END_ALLOW_THREADS
  
 -      if (!cpy_num_callbacks) {
 +  if (!cpy_num_callbacks) {
      Py_Finalize();
      return 0;
    }
@@@ -1201,7 -1171,7 +1199,7 @@@ PyMODINIT_FUNC PyInit_collectd(void) 
  
  static int cpy_init_python(void) {
    PyOS_sighandler_t cur_sig;
 -  PyObject *sys;
 +  PyObject *sys, *errordict;
    PyObject *module;
  
  #ifdef IS_PY3K
    PyType_Ready(&SignedType);
    UnsignedType.tp_base = &PyLong_Type;
    PyType_Ready(&UnsignedType);
 +  errordict = PyDict_New();
 +  PyDict_SetItemString(errordict, "__doc__", cpy_string_to_unicode_or_bytes(CollectdError_doc)); /* New reference. */
 +  CollectdError = PyErr_NewException("collectd.CollectdError", NULL, errordict);
    sys = PyImport_ImportModule("sys"); /* New reference. */
    if (sys == NULL) {
      cpy_log_exception("python initialization");
                       (void *)&SignedType); /* Steals a reference. */
    PyModule_AddObject(module, "Unsigned",
                       (void *)&UnsignedType); /* Steals a reference. */
 +  Py_XINCREF(CollectdError);
 +  PyModule_AddObject(module, "CollectdError", CollectdError); /* Steals a reference. */
    PyModule_AddIntConstant(module, "LOG_DEBUG", LOG_DEBUG);
    PyModule_AddIntConstant(module, "LOG_INFO", LOG_INFO);
    PyModule_AddIntConstant(module, "LOG_NOTICE", LOG_NOTICE);