Skip to content

Commit ddd6333

Browse files
Add the python3 plugin to the build system. (#202)
* python plugin: Allow overriding plugin name. * Use RTLD_DEEPBIND when loading plugins, in case of symbol conflict.
1 parent 98b4dc7 commit ddd6333

File tree

4 files changed

+124
-29
lines changed

4 files changed

+124
-29
lines changed

Makefile.am

+12
Original file line numberDiff line numberDiff line change
@@ -1481,6 +1481,18 @@ python_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBPYTHON_CPPFLAGS)
14811481
python_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(LIBPYTHON_LDFLAGS)
14821482
endif
14831483

1484+
if BUILD_PLUGIN_PYTHON3
1485+
pkglib_LTLIBRARIES += python3.la
1486+
python3_la_SOURCES = \
1487+
src/python.c \
1488+
src/pyconfig.c \
1489+
src/pyvalues.c \
1490+
src/cpython.h
1491+
python3_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBPYTHON3_CPPFLAGS) \
1492+
-DPLUGIN_NAME='"python3"'
1493+
python3_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(LIBPYTHON3_LDFLAGS)
1494+
endif
1495+
14841496
if BUILD_PLUGIN_PROCESSES
14851497
pkglib_LTLIBRARIES += processes.la
14861498
processes_la_SOURCES = src/processes.c

configure.ac

+82-4
Original file line numberDiff line numberDiff line change
@@ -4623,11 +4623,11 @@ AC_ARG_WITH([libpython],
46234623
[with_libpython="check"]
46244624
)
46254625
4626-
if test "$with_libpython" != "no"; then
4626+
if test "x$with_libpython" != "xno"; then
46274627
if test "$LIBPYTHON_CPPFLAGS" = "" && test "$LIBPYTHON_LDFLAGS" = ""; then
46284628
AC_ARG_VAR([PYTHON_CONFIG], [path to python-config])
46294629
AC_PATH_PROGS([PYTHON_CONFIG],
4630-
[python3-config python2-config python-config]
4630+
[python2-config python-config]
46314631
)
46324632
if test "$PYTHON_CONFIG" = ""; then
46334633
if test "$with_libpython" = "yes"; then
@@ -4653,7 +4653,7 @@ if test "$PYTHON_CONFIG" != ""; then
46534653
fi
46544654
fi
46554655
4656-
if test "$with_libpython" != "xno"; then
4656+
if test "x$with_libpython" != "xno"; then
46574657
SAVE_CPPFLAGS="$CPPFLAGS"
46584658
SAVE_LDFLAGS="$LDFLAGS"
46594659
SAVE_LIBS="$LIBS"
@@ -4682,6 +4682,76 @@ if test "$with_libpython" != "xno"; then
46824682
fi
46834683
# }}} --with-libpython
46844684
4685+
# --with-libpython3 {{{
4686+
AC_ARG_VAR([LIBPYTHON3_CPPFLAGS], [Preprocessor flags for libpython3])
4687+
AC_ARG_VAR([LIBPYTHON3_LDFLAGS], [Linker flags for libpython3])
4688+
AC_ARG_VAR([LIBPYTHON3_LIBS], [Libraries for libpython3])
4689+
4690+
AC_ARG_WITH([libpython3],
4691+
[AS_HELP_STRING([--with-libpython3], [if we should build with libpython3 @<:@default=yes@:>@])],
4692+
[with_libpython3="$withval"],
4693+
[with_libpython3="check"]
4694+
)
4695+
4696+
if test "x$with_libpython3" != "xno"; then
4697+
if test "$LIBPYTHON3_CPPFLAGS" = "" && test "$LIBPYTHON3_LDFLAGS" = ""; then
4698+
AC_ARG_VAR([PYTHON3_CONFIG], [path to python3-config])
4699+
AC_PATH_PROGS([PYTHON3_CONFIG],
4700+
[python3-config]
4701+
)
4702+
if test "$PYTHON3_CONFIG" = ""; then
4703+
if test "$with_libpython3" = "yes"; then
4704+
AC_MSG_ERROR([Unable to find python3-config])
4705+
fi
4706+
with_libpython3="no"
4707+
fi
4708+
fi
4709+
fi
4710+
4711+
if test "$PYTHON3_CONFIG" != ""; then
4712+
LIBPYTHON3_CPPFLAGS="`${PYTHON3_CONFIG} --includes`"
4713+
if test $? -ne 0; then
4714+
with_libpython3="no"
4715+
fi
4716+
LIBPYTHON3_LDFLAGS="`${PYTHON3_CONFIG} --ldflags`"
4717+
if test $? -ne 0; then
4718+
with_libpython3="no"
4719+
fi
4720+
LIBPYTHON3_LIBS="`${PYTHON3_CONFIG} --libs`"
4721+
if test $? -ne 0; then
4722+
with_libpython3="no"
4723+
fi
4724+
fi
4725+
4726+
if test "x$with_libpython3" != "xno"; then
4727+
SAVE_CPPFLAGS="$CPPFLAGS"
4728+
SAVE_LDFLAGS="$LDFLAGS"
4729+
SAVE_LIBS="$LIBS"
4730+
CPPFLAGS="$LIBPYTHON3_CPPFLAGS $CPPFLAGS"
4731+
LDFLAGS="$LIBPYTHON3_LDFLAGS $LDFLAGS"
4732+
LIBS="$LIBPYTHON3_LIBS $LIBS"
4733+
4734+
AC_CHECK_HEADERS([Python.h],
4735+
[
4736+
AC_MSG_CHECKING([for libpython3])
4737+
AC_LINK_IFELSE([AC_LANG_PROGRAM(
4738+
[[#include <Python.h>]],
4739+
[[Py_Initialize();]])
4740+
],
4741+
[with_libpython3="yes"],
4742+
[with_libpython3="no"]
4743+
)
4744+
AC_MSG_RESULT([$with_libpython3])
4745+
],
4746+
[with_libpython3="no"]
4747+
)
4748+
4749+
CPPFLAGS="$SAVE_CPPFLAGS"
4750+
LDFLAGS="$SAVE_LDFLAGS"
4751+
LIBS="$SAVE_LIBS"
4752+
fi
4753+
# }}} --with-libpython3
4754+
46854755
# --with-librabbitmq {{{
46864756
AC_ARG_WITH([librabbitmq],
46874757
[AS_HELP_STRING([--with-librabbitmq@<:@=PREFIX@:>@], [Path to librabbitmq.])],
@@ -6206,6 +6276,7 @@ plugin_pinba="no"
62066276
plugin_processes="no"
62076277
plugin_protocols="no"
62086278
plugin_python="no"
6279+
plugin_python3="no"
62096280
plugin_serial="no"
62106281
plugin_smart="no"
62116282
plugin_swap="no"
@@ -6494,6 +6565,10 @@ if test "x$with_libpython" != "xno"; then
64946565
plugin_python="yes"
64956566
fi
64966567
6568+
if test "x$with_libpython3" != "xno"; then
6569+
plugin_python3="yes"
6570+
fi
6571+
64976572
if test "x$with_libatasmart" = "xyes" && test "x$with_libudev" = "xyes"; then
64986573
plugin_smart="yes"
64996574
fi
@@ -6664,7 +6739,8 @@ AC_PLUGIN([postgresql], [$with_libpq], [PostgreSQL database
66646739
AC_PLUGIN([powerdns], [yes], [PowerDNS statistics])
66656740
AC_PLUGIN([processes], [$plugin_processes], [Process statistics])
66666741
AC_PLUGIN([protocols], [$plugin_protocols], [Protocol (IP, TCP, ...) statistics])
6667-
AC_PLUGIN([python], [$plugin_python], [Embed a Python interpreter])
6742+
AC_PLUGIN([python], [$plugin_python], [Embed a Python 2 interpreter])
6743+
AC_PLUGIN([python3], [$plugin_python3], [Embed a Python 3 interpreter])
66686744
AC_PLUGIN([redis], [$with_libhiredis], [Redis plugin])
66696745
AC_PLUGIN([routeros], [$with_librouteros], [RouterOS plugin])
66706746
AC_PLUGIN([rrdcached], [$librrd_rrdc_update], [RRDTool output plugin])
@@ -6960,6 +7036,7 @@ AC_MSG_RESULT([ libprotobuf . . . . . $with_libprotobuf])
69607036
AC_MSG_RESULT([ libprotobuf-c . . . . $with_libprotobuf_c])
69617037
AC_MSG_RESULT([ libpthread . . . . . $with_libpthread])
69627038
AC_MSG_RESULT([ libpython . . . . . . $with_libpython])
7039+
AC_MSG_RESULT([ libpython3 . . . . . $with_libpython3])
69637040
AC_MSG_RESULT([ librabbitmq . . . . . $with_librabbitmq])
69647041
AC_MSG_RESULT([ libriemann-client . . $with_libriemann_client])
69657042
AC_MSG_RESULT([ librdkafka . . . . . $with_librdkafka])
@@ -7094,6 +7171,7 @@ AC_MSG_RESULT([ powerdns . . . . . . $enable_powerdns])
70947171
AC_MSG_RESULT([ processes . . . . . . $enable_processes])
70957172
AC_MSG_RESULT([ protocols . . . . . . $enable_protocols])
70967173
AC_MSG_RESULT([ python . . . . . . . $enable_python])
7174+
AC_MSG_RESULT([ python3 . . . . . . . $enable_python3])
70977175
AC_MSG_RESULT([ redis . . . . . . . . $enable_redis])
70987176
AC_MSG_RESULT([ routeros . . . . . . $enable_routeros])
70997177
AC_MSG_RESULT([ rrdcached . . . . . . $enable_rrdcached])

src/daemon/plugin.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -397,7 +397,7 @@ static int plugin_unregister(llist_t *list, const char *name) /* {{{ */
397397
static int plugin_load_file(const char *file, _Bool global) {
398398
void (*reg_handle)(void);
399399

400-
int flags = RTLD_NOW;
400+
int flags = RTLD_NOW | RTLD_DEEPBIND;
401401
if (global)
402402
flags |= RTLD_GLOBAL;
403403

src/python.c

+29-24
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@
3535

3636
#include "cpython.h"
3737

38+
#ifndef PLUGIN_NAME
39+
#define PLUGIN_NAME "python"
40+
#endif
41+
3842
typedef struct cpy_callback_s {
3943
char *name;
4044
PyObject *callback;
@@ -816,7 +820,7 @@ static PyObject *cpy_register_read(PyObject *self, PyObject *args,
816820
c->next = NULL;
817821

818822
plugin_register_complex_read(
819-
/* group = */ "python", buf, cpy_read_callback,
823+
/* group = */ PLUGIN_NAME, buf, cpy_read_callback,
820824
DOUBLE_TO_CDTIME_T(interval),
821825
&(user_data_t){
822826
.data = c,
@@ -1153,7 +1157,7 @@ static void *cpy_interactive(void *pipefd) {
11531157
PyOS_setsig(SIGINT, cur_sig);
11541158
PyErr_Print();
11551159
state = PyEval_SaveThread();
1156-
NOTICE("python: Interactive interpreter exited, stopping collectd ...");
1160+
NOTICE(PLUGIN_NAME ": Interactive interpreter exited, stopping collectd ...");
11571161
pthread_kill(main_thread, SIGINT);
11581162
return NULL;
11591163
}
@@ -1165,20 +1169,20 @@ static int cpy_init(void) {
11651169
static pthread_t thread;
11661170

11671171
if (!Py_IsInitialized()) {
1168-
WARNING("python: Plugin loaded but not configured.");
1169-
plugin_unregister_shutdown("python");
1172+
WARNING(PLUGIN_NAME ": Plugin loaded but not configured.");
1173+
plugin_unregister_shutdown(PLUGIN_NAME);
11701174
Py_Finalize();
11711175
return 0;
11721176
}
11731177
main_thread = pthread_self();
11741178
if (do_interactive) {
11751179
if (pipe(pipefd)) {
1176-
ERROR("python: Unable to create pipe.");
1180+
ERROR(PLUGIN_NAME ": Unable to create pipe.");
11771181
return 1;
11781182
}
11791183
if (plugin_thread_create(&thread, NULL, cpy_interactive, pipefd + 1,
1180-
"python interpreter")) {
1181-
ERROR("python: Error creating thread for interactive interpreter.");
1184+
PLUGIN_NAME " interpreter")) {
1185+
ERROR(PLUGIN_NAME ": Error creating thread for interactive interpreter.");
11821186
}
11831187
if (read(pipefd[0], &buf, 1))
11841188
;
@@ -1290,13 +1294,13 @@ static int cpy_init_python(void) {
12901294
CollectdError = PyErr_NewException("collectd.CollectdError", NULL, errordict);
12911295
sys = PyImport_ImportModule("sys"); /* New reference. */
12921296
if (sys == NULL) {
1293-
cpy_log_exception("python initialization");
1297+
cpy_log_exception(PLUGIN_NAME " initialization");
12941298
return 1;
12951299
}
12961300
sys_path = PyObject_GetAttrString(sys, "path"); /* New reference. */
12971301
Py_DECREF(sys);
12981302
if (sys_path == NULL) {
1299-
cpy_log_exception("python initialization");
1303+
cpy_log_exception(PLUGIN_NAME " initialization");
13001304
return 1;
13011305
}
13021306
PySys_SetArgv(1, &argv);
@@ -1368,8 +1372,8 @@ static int cpy_config(oconfig_item_t *ci) {
13681372
continue;
13691373
}
13701374
#ifdef IS_PY3K
1371-
ERROR("python: \"Encoding\" was used in the config file but Python3 was "
1372-
"used, which does not support changing encodings");
1375+
ERROR(PLUGIN_NAME ": \"Encoding\" was used in the config file but "
1376+
"Python3 was used, which does not support changing encodings");
13731377
status = 1;
13741378
sfree(encoding);
13751379
continue;
@@ -1396,15 +1400,15 @@ static int cpy_config(oconfig_item_t *ci) {
13961400
continue;
13971401
tb = PyImport_ImportModule("traceback"); /* New reference. */
13981402
if (tb == NULL) {
1399-
cpy_log_exception("python initialization");
1403+
cpy_log_exception(PLUGIN_NAME " initialization");
14001404
status = 1;
14011405
continue;
14021406
}
14031407
cpy_format_exception =
14041408
PyObject_GetAttrString(tb, "format_exception"); /* New reference. */
14051409
Py_DECREF(tb);
14061410
if (cpy_format_exception == NULL) {
1407-
cpy_log_exception("python initialization");
1411+
cpy_log_exception(PLUGIN_NAME " initialization");
14081412
status = 1;
14091413
}
14101414
} else if (strcasecmp(item->key, "ModulePath") == 0) {
@@ -1417,19 +1421,19 @@ static int cpy_config(oconfig_item_t *ci) {
14171421
}
14181422
dir_object = cpy_string_to_unicode_or_bytes(dir); /* New reference. */
14191423
if (dir_object == NULL) {
1420-
ERROR("python plugin: Unable to convert \"%s\" to "
1424+
ERROR(PLUGIN_NAME " plugin: Unable to convert \"%s\" to "
14211425
"a python object.",
14221426
dir);
14231427
free(dir);
1424-
cpy_log_exception("python initialization");
1428+
cpy_log_exception(PLUGIN_NAME " initialization");
14251429
status = 1;
14261430
continue;
14271431
}
14281432
if (PyList_Insert(sys_path, 0, dir_object) != 0) {
1429-
ERROR("python plugin: Unable to prepend \"%s\" to "
1433+
ERROR(PLUGIN_NAME " plugin: Unable to prepend \"%s\" to "
14301434
"python module path.",
14311435
dir);
1432-
cpy_log_exception("python initialization");
1436+
cpy_log_exception(PLUGIN_NAME " initialization");
14331437
status = 1;
14341438
}
14351439
Py_DECREF(dir_object);
@@ -1444,7 +1448,8 @@ static int cpy_config(oconfig_item_t *ci) {
14441448
}
14451449
module = PyImport_ImportModule(module_name); /* New reference. */
14461450
if (module == NULL) {
1447-
ERROR("python plugin: Error importing module \"%s\".", module_name);
1451+
ERROR(PLUGIN_NAME " plugin: Error importing module \"%s\".",
1452+
module_name);
14481453
cpy_log_exception("importing module");
14491454
status = 1;
14501455
}
@@ -1464,8 +1469,8 @@ static int cpy_config(oconfig_item_t *ci) {
14641469
break;
14651470
}
14661471
if (c == NULL) {
1467-
WARNING("python plugin: Found a configuration for the \"%s\" plugin, "
1468-
"but the plugin isn't loaded or didn't register "
1472+
WARNING(PLUGIN_NAME " plugin: Found a configuration for the \"%s\" "
1473+
"plugin, but the plugin isn't loaded or didn't register "
14691474
"a configuration callback.",
14701475
name);
14711476
free(name);
@@ -1486,15 +1491,15 @@ static int cpy_config(oconfig_item_t *ci) {
14861491
} else
14871492
Py_DECREF(ret);
14881493
} else {
1489-
ERROR("python plugin: Unknown config key \"%s\".", item->key);
1494+
ERROR(PLUGIN_NAME " plugin: Unknown config key \"%s\".", item->key);
14901495
status = 1;
14911496
}
14921497
}
14931498
return status;
14941499
}
14951500

14961501
void module_register(void) {
1497-
plugin_register_complex_config("python", cpy_config);
1498-
plugin_register_init("python", cpy_init);
1499-
plugin_register_shutdown("python", cpy_shutdown);
1502+
plugin_register_complex_config(PLUGIN_NAME, cpy_config);
1503+
plugin_register_init(PLUGIN_NAME, cpy_init);
1504+
plugin_register_shutdown(PLUGIN_NAME, cpy_shutdown);
15001505
}

0 commit comments

Comments
 (0)