summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 17f5d59)
raw | patch | inline | side by side (parent: 17f5d59)
author | Sven Trenkel <collectd@semidefinite.de> | |
Mon, 15 Aug 2016 21:47:34 +0000 (21:47 +0000) | ||
committer | Florian Forster <octo@collectd.org> | |
Tue, 16 Aug 2016 05:19:53 +0000 (07:19 +0200) |
src/python.c | patch | blob | history |
diff --git a/src/python.c b/src/python.c
index 94058421fbe053874befb6190d9c9b7cd9bed723..1a7359cd526a5d9a5e7e725dc77671d88cf6d29d 100644 (file)
--- a/src/python.c
+++ b/src/python.c
static cpy_callback_t *cpy_init_callbacks;
static cpy_callback_t *cpy_shutdown_callbacks;
+/* Make sure to hold the GIL while modifying these. */
+static int cpy_shutdown_triggered = 0;
+static int cpy_num_callbacks = 0;
+
static void cpy_destroy_user_data(void *data) {
cpy_callback_t *c = data;
free(c->name);
CPY_LOCK_THREADS
Py_DECREF(c->callback);
Py_XDECREF(c->data);
- CPY_RELEASE_THREADS
free(c);
+ --cpy_num_callbacks;
+ if (!cpy_num_callbacks && cpy_shutdown_triggered) {
+ Py_Finalize();
+ return;
+ }
+ CPY_RELEASE_THREADS
}
/* You must hold the GIL to call this function!
@@ -565,6 +574,7 @@ static PyObject *cpy_register_generic(cpy_callback_t **list_head, PyObject *args
c->callback = callback;
c->data = data;
c->next = *list_head;
+ ++cpy_num_callbacks;
*list_head = c;
Py_XDECREF(mod);
PyMem_Free(name);
@@ -661,6 +671,7 @@ static PyObject *cpy_register_generic_userdata(void *reg, void *handler, PyObjec
};
register_function(buf, handler, &user_data);
+ ++cpy_num_callbacks;
return cpy_string_to_unicode_or_bytes(buf);
}
@@ -700,6 +711,7 @@ static PyObject *cpy_register_read(PyObject *self, PyObject *args, PyObject *kwd
plugin_register_complex_read(/* group = */ "python", buf,
cpy_read_callback, DOUBLE_TO_CDTIME_T (interval), &user_data);
+ ++cpy_num_callbacks;
return cpy_string_to_unicode_or_bytes(buf);
}
static int cpy_shutdown(void) {
PyObject *ret;
- /* This can happen if the module was loaded but not configured. */
- if (state != NULL)
- PyEval_RestoreThread(state);
+ PyEval_RestoreThread(state);
for (cpy_callback_t *c = cpy_shutdown_callbacks; c; c = c->next) {
ret = PyObject_CallFunctionObjArgs(c->callback, c->data, (void *) 0); /* New reference. */
cpy_unregister_list(&cpy_config_callbacks);
cpy_unregister_list(&cpy_init_callbacks);
cpy_unregister_list(&cpy_shutdown_callbacks);
+ cpy_shutdown_triggered = 1;
+
+ if (!cpy_num_callbacks)
+ Py_Finalize();
- Py_Finalize();
return 0;
}
if (!Py_IsInitialized()) {
WARNING("python: Plugin loaded but not configured.");
plugin_unregister_shutdown("python");
+ Py_Finalize();
return 0;
}
PyEval_InitThreads();