"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;
}
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);
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) {
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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
}
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;
}
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);