summaryrefslogtreecommitdiff
path: root/pythonmod
diff options
context:
space:
mode:
authorCy Schubert <cy@FreeBSD.org>2019-12-28 05:27:06 +0000
committerCy Schubert <cy@FreeBSD.org>2019-12-28 05:27:06 +0000
commite2fe726866d062155f6b1aae749375475ef19191 (patch)
treefe6b00611d5c987d2c12c32063891ae19295ffeb /pythonmod
parent366b94c4a9552acfb560d3234aea0955ebc1eb8e (diff)
Diffstat (limited to 'pythonmod')
-rw-r--r--pythonmod/examples/calc.py8
-rw-r--r--pythonmod/interface.i7
-rw-r--r--pythonmod/pythonmod.c85
3 files changed, 65 insertions, 35 deletions
diff --git a/pythonmod/examples/calc.py b/pythonmod/examples/calc.py
index 3230e37e3eea6..8c15f50b9d75c 100644
--- a/pythonmod/examples/calc.py
+++ b/pythonmod/examples/calc.py
@@ -45,9 +45,13 @@ def operate(id, event, qstate, qdata):
if (event == MODULE_EVENT_NEW) or (event == MODULE_EVENT_PASS):
- if qstate.qinfo.qname_str.endswith("._calc_.cz."):
+ if qstate.qinfo.qname_str.endswith("._calc_.cz.") and not ("__" in qstate.qinfo.qname_str):
try:
- res = eval(''.join(qstate.qinfo.qname_list[0:-3]))
+ # the second and third argument to eval attempt to restrict
+ # functions and variables available to stop code execution
+ # but it may not be safe either. This is why __ substrings
+ # are excluded from evaluation.
+ res = eval(''.join(qstate.qinfo.qname_list[0:-3]),{"__builtins__":None},{})
except:
res = "exception"
diff --git a/pythonmod/interface.i b/pythonmod/interface.i
index 14f0299eeb575..c02ebaf951d0b 100644
--- a/pythonmod/interface.i
+++ b/pythonmod/interface.i
@@ -4,6 +4,9 @@
%begin %{
/* store state of warning output, restored at later pop */
#pragma GCC diagnostic push
+/* ignore warnings for pragma below, where for older GCC it can produce a
+ warning if the cast-function-type warning is absent. */
+#pragma GCC diagnostic ignored "-Wpragmas"
/* ignore gcc8 METH_NOARGS function cast warnings for swig function pointers */
#pragma GCC diagnostic ignored "-Wcast-function-type"
%}
@@ -1011,7 +1014,7 @@ struct config_file {
char* control_key_file;
char* control_cert_file;
int do_daemonize;
- char* python_script;
+ struct config_strlist* python_script;
};
/* ************************************************************************************ *
@@ -1106,6 +1109,7 @@ struct delegpt {
%rename ("MODULE_STATE_INITIAL") "module_state_initial";
%rename ("MODULE_WAIT_REPLY") "module_wait_reply";
%rename ("MODULE_WAIT_MODULE") "module_wait_module";
+%rename ("MODULE_RESTART_NEXT") "module_restart_next";
%rename ("MODULE_WAIT_SUBQUERY") "module_wait_subquery";
%rename ("MODULE_ERROR") "module_error";
%rename ("MODULE_FINISHED") "module_finished";
@@ -1114,6 +1118,7 @@ enum module_ext_state {
module_state_initial = 0,
module_wait_reply,
module_wait_module,
+ module_restart_next,
module_wait_subquery,
module_error,
module_finished
diff --git a/pythonmod/pythonmod.c b/pythonmod/pythonmod.c
index 9009a28daaa06..9006429efff52 100644
--- a/pythonmod/pythonmod.c
+++ b/pythonmod/pythonmod.c
@@ -65,6 +65,15 @@ typedef void* PyGILState_STATE;
#endif
/**
+ * counter for python module instances
+ * incremented by pythonmod_init(...)
+ */
+int py_mod_count = 0;
+
+/** Python main thread */
+PyThreadState* mainthr;
+
+/**
* Global state for the module.
*/
struct pythonmod_env {
@@ -72,8 +81,6 @@ struct pythonmod_env {
/** Python script filename. */
const char* fname;
- /** Python main thread */
- PyThreadState* mainthr;
/** Python module. */
PyObject* module;
@@ -242,14 +249,17 @@ cleanup:
int pythonmod_init(struct module_env* env, int id)
{
+ int py_mod_idx = py_mod_count++;
+
/* Initialize module */
FILE* script_py = NULL;
PyObject* py_init_arg, *res;
PyGILState_STATE gil;
- int init_standard = 1;
+ int init_standard = 1, i = 0;
#if PY_MAJOR_VERSION < 3
PyObject* PyFileObject = NULL;
#endif
+ struct config_strlist* cfg_item = env->cfg->python_script;
struct pythonmod_env* pe = (struct pythonmod_env*)calloc(1, sizeof(struct pythonmod_env));
if (!pe)
@@ -261,14 +271,21 @@ int pythonmod_init(struct module_env* env, int id)
env->modinfo[id] = (void*) pe;
/* Initialize module */
- pe->fname = env->cfg->python_script;
+ pe->fname=NULL; i = 0;
+ while (cfg_item!=NULL) {
+ if (py_mod_idx==i++) {
+ pe->fname=cfg_item->str;
+ break;
+ }
+ cfg_item = cfg_item->next;
+ }
if(pe->fname==NULL || pe->fname[0]==0) {
- log_err("pythonmod: no script given.");
+ log_err("pythonmod[%d]: no script given.", py_mod_idx);
return 0;
}
/* Initialize Python libraries */
- if (!Py_IsInitialized())
+ if (py_mod_count==1 && !Py_IsInitialized())
{
#if PY_MAJOR_VERSION >= 3
wchar_t progname[8];
@@ -284,29 +301,31 @@ int pythonmod_init(struct module_env* env, int id)
Py_Initialize();
PyEval_InitThreads();
SWIG_init();
- pe->mainthr = PyEval_SaveThread();
+ mainthr = PyEval_SaveThread();
}
gil = PyGILState_Ensure();
- /* Initialize Python */
- PyRun_SimpleString("import sys \n");
- PyRun_SimpleString("sys.path.append('.') \n");
- if(env->cfg->directory && env->cfg->directory[0]) {
- char wdir[1524];
- snprintf(wdir, sizeof(wdir), "sys.path.append('%s') \n",
- env->cfg->directory);
- PyRun_SimpleString(wdir);
- }
- PyRun_SimpleString("sys.path.append('"RUN_DIR"') \n");
- PyRun_SimpleString("sys.path.append('"SHARE_DIR"') \n");
- PyRun_SimpleString("import distutils.sysconfig \n");
- PyRun_SimpleString("sys.path.append(distutils.sysconfig.get_python_lib(1,0)) \n");
- if (PyRun_SimpleString("from unboundmodule import *\n") < 0)
- {
- log_err("pythonmod: cannot initialize core module: unboundmodule.py");
- PyGILState_Release(gil);
- return 0;
+ if (py_mod_count==1) {
+ /* Initialize Python */
+ PyRun_SimpleString("import sys \n");
+ PyRun_SimpleString("sys.path.append('.') \n");
+ if(env->cfg->directory && env->cfg->directory[0]) {
+ char wdir[1524];
+ snprintf(wdir, sizeof(wdir), "sys.path.append('%s') \n",
+ env->cfg->directory);
+ PyRun_SimpleString(wdir);
+ }
+ PyRun_SimpleString("sys.path.append('"RUN_DIR"') \n");
+ PyRun_SimpleString("sys.path.append('"SHARE_DIR"') \n");
+ PyRun_SimpleString("import distutils.sysconfig \n");
+ PyRun_SimpleString("sys.path.append(distutils.sysconfig.get_python_lib(1,0)) \n");
+ if (PyRun_SimpleString("from unboundmodule import *\n") < 0)
+ {
+ log_err("pythonmod: cannot initialize core module: unboundmodule.py");
+ PyGILState_Release(gil);
+ return 0;
+ }
}
/* Check Python file load */
@@ -328,8 +347,8 @@ int pythonmod_init(struct module_env* env, int id)
/* Load file */
pe->module = PyImport_AddModule("__main__");
pe->dict = PyModule_GetDict(pe->module);
- pe->data = Py_None;
- Py_INCREF(pe->data);
+ pe->data = PyDict_New();
+ Py_XINCREF(pe->data);
PyModule_AddObject(pe->module, "mod_env", pe->data);
/* TODO: deallocation of pe->... if an error occurs */
@@ -352,6 +371,7 @@ int pythonmod_init(struct module_env* env, int id)
(void)PyParser_SimpleParseFile(script_py, pe->fname, Py_file_input);
log_py_err();
PyGILState_Release(gil);
+ fclose(script_py);
return 0;
}
#if PY_MAJOR_VERSION < 3
@@ -440,9 +460,11 @@ void pythonmod_deinit(struct module_env* env, int id)
Py_XDECREF(pe->data);
PyGILState_Release(gil);
- PyEval_RestoreThread(pe->mainthr);
- Py_Finalize();
- pe->mainthr = NULL;
+ if(--py_mod_count==0) {
+ PyEval_RestoreThread(mainthr);
+ Py_Finalize();
+ mainthr = NULL;
+ }
}
pe->fname = NULL;
free(pe);
@@ -500,8 +522,7 @@ void pythonmod_operate(struct module_qstate* qstate, enum module_ev event,
pq = qstate->minfo[id] = malloc(sizeof(struct pythonmod_qstate));
/* Initialize per query data */
- pq->data = Py_None;
- Py_INCREF(pq->data);
+ pq->data = PyDict_New();
}
/* Call operate */