Home | History | Annotate | Line # | Download | only in pythonmod
      1 /*
      2  * pythonmod.c: unbound module C wrapper
      3  *
      4  * Copyright (c) 2009, Zdenek Vasicek (vasicek AT fit.vutbr.cz)
      5  *                     Marek Vavrusa  (xvavru00 AT stud.fit.vutbr.cz)
      6  *
      7  * This software is open source.
      8  *
      9  * Redistribution and use in source and binary forms, with or without
     10  * modification, are permitted provided that the following conditions
     11  * are met:
     12  *
     13  *    * Redistributions of source code must retain the above copyright notice,
     14  *      this list of conditions and the following disclaimer.
     15  *
     16  *    * Redistributions in binary form must reproduce the above copyright notice,
     17  *      this list of conditions and the following disclaimer in the documentation
     18  *      and/or other materials provided with the distribution.
     19  *
     20  *    * Neither the name of the organization nor the names of its
     21  *      contributors may be used to endorse or promote products derived from this
     22  *      software without specific prior written permission.
     23  *
     24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     25  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     26  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     27  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
     28  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     29  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     30  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     31  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     32  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     33  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     34  * POSSIBILITY OF SUCH DAMAGE.
     35  */
     36 /**
     37  * \file
     38  * Python module for unbound.  Calls python script.
     39  */
     40 
     41 /* ignore the varargs unused warning from SWIGs internal vararg support */
     42 #ifdef __GNUC__
     43 #pragma GCC diagnostic ignored "-Wunused-parameter"
     44 #ifndef __clang__
     45 #pragma GCC diagnostic ignored "-Wunused-but-set-variable"
     46 #endif
     47 #endif
     48 
     49 #include "config.h"
     50 #include "sldns/sbuffer.h"
     51 
     52 #undef _POSIX_C_SOURCE
     53 #undef _XOPEN_SOURCE
     54 #include <Python.h>
     55 
     56 #include "pythonmod/pythonmod.h"
     57 #include "util/module.h"
     58 #include "util/config_file.h"
     59 #include "pythonmod_utils.h"
     60 
     61 #ifdef S_SPLINT_S
     62 typedef struct PyObject PyObject;
     63 typedef struct PyThreadState PyThreadState;
     64 typedef void* PyGILState_STATE;
     65 #endif
     66 
     67 /**
     68  *  counter for python module instances
     69  *  incremented by pythonmod_init(...)
     70  */
     71 int py_mod_count = 0;
     72 
     73 /** Python main thread */
     74 PyThreadState* mainthr;
     75 
     76 /**
     77  * Global state for the module.
     78  */
     79 struct pythonmod_env {
     80 
     81 	/** Python script filename. */
     82 	const char* fname;
     83 
     84 	/** Python module. */
     85 	PyObject* module;
     86 
     87 	/** Module init function */
     88 	PyObject* func_init;
     89 	/** Module deinit function */
     90 	PyObject* func_deinit;
     91 	/** Module operate function */
     92 	PyObject* func_operate;
     93 	/** Module super_inform function */
     94 	PyObject* func_inform;
     95 
     96 	/** Python dictionary. */
     97 	PyObject* dict;
     98 
     99 	/** Module data. */
    100 	PyObject* data;
    101 
    102 	/** Module qstate. */
    103 	struct module_qstate* qstate;
    104 };
    105 
    106 /**
    107  * Per query state for the iterator module.
    108  */
    109 struct pythonmod_qstate {
    110 
    111 	/** Module per query data. */
    112 	PyObject* data;
    113 };
    114 
    115 /* The dict from __main__ could have remnants from a previous script
    116  * invocation, in a multi python module setup. Usually this is fine since newer
    117  * scripts will update their values. The obvious erroneous case is when mixing
    118  * python scripts that make use of both 'init' and 'init_standard'. This
    119  * results in 'init_standard' to persist on following scripts that don't use it
    120  * (thus not replacing it). This is also problematic in case where a script
    121  * does not define a required function but a previously loaded script did. The
    122  * current solution is to make sure to clean offensive remnants that influence
    123  * further parsing of the individual scripts.
    124  */
    125 static void
    126 clean_python_function_objects(PyObject* dict) {
    127 	const char* function_names[] = {
    128 		"init",
    129 		"init_standard",
    130 		"deinit",
    131 		"operate",
    132 		"inform_super"
    133 	};
    134 	size_t i;
    135 
    136 	for(i=0; i<sizeof(function_names)/sizeof(function_names[0]); i++) {
    137 		if(PyDict_GetItemString(dict, function_names[i]) != NULL) {
    138 			PyDict_DelItemString(dict, function_names[i]);
    139 		}
    140 	}
    141 };
    142 
    143 /* Generated */
    144 #ifndef S_SPLINT_S
    145 #include "pythonmod/interface.h"
    146 #endif
    147 
    148 /** log python error */
    149 static void
    150 log_py_err(void)
    151 {
    152 	char *result = NULL;
    153 	const char* iomod = "cStringIO";
    154 	PyObject *modStringIO = NULL;
    155 	PyObject *modTB = NULL;
    156 	PyObject *obFuncStringIO = NULL;
    157 	PyObject *obStringIO = NULL;
    158 	PyObject *obFuncTB = NULL;
    159 	PyObject *argsTB = NULL;
    160 	PyObject *obResult = NULL;
    161 	PyObject *ascstr = NULL;
    162 	PyObject *exc_typ, *exc_val, *exc_tb;
    163 
    164 	/* Fetch the error state now before we cruch it */
    165 	/* exc val contains the error message
    166 	 * exc tb contains stack traceback and other info. */
    167 	PyErr_Fetch(&exc_typ, &exc_val, &exc_tb);
    168 	PyErr_NormalizeException(&exc_typ, &exc_val, &exc_tb);
    169 
    170 	/* Import the modules we need - cStringIO and traceback */
    171 	modStringIO = PyImport_ImportModule("cStringIO");
    172 	if (modStringIO==NULL) {
    173 		/* python 1.4 and before */
    174 		modStringIO = PyImport_ImportModule("StringIO");
    175 		iomod = "StringIO";
    176 	}
    177 	if (modStringIO==NULL) {
    178 		/* python 3 */
    179 		modStringIO = PyImport_ImportModule("io");
    180 		iomod = "io";
    181 	}
    182 	if (modStringIO==NULL) {
    183 		log_err("pythonmod: cannot print exception, "
    184 			"cannot ImportModule cStringIO or StringIO or io");
    185 		goto cleanup;
    186 	}
    187 	modTB = PyImport_ImportModule("traceback");
    188 	if (modTB==NULL) {
    189 		log_err("pythonmod: cannot print exception, "
    190 			"cannot ImportModule traceback");
    191 		goto cleanup;
    192 	}
    193 
    194 	/* Construct a cStringIO object */
    195 	obFuncStringIO = PyObject_GetAttrString(modStringIO, "StringIO");
    196 	if (obFuncStringIO==NULL) {
    197 		log_err("pythonmod: cannot print exception, "
    198 			"cannot GetAttrString %s.StringIO", iomod);
    199 		goto cleanup;
    200 	}
    201 	obStringIO = PyObject_CallObject(obFuncStringIO, NULL);
    202 	if (obStringIO==NULL) {
    203 		log_err("pythonmod: cannot print exception, "
    204 			"cannot call %s.StringIO()", iomod);
    205 		goto cleanup;
    206 	}
    207 
    208 	/* Get the traceback.print_exception function, and call it. */
    209 	obFuncTB = PyObject_GetAttrString(modTB, "print_exception");
    210 	if (obFuncTB==NULL) {
    211 		log_err("pythonmod: cannot print exception, "
    212 			"cannot GetAttrString traceback.print_exception");
    213 		goto cleanup;
    214 	}
    215 	argsTB = Py_BuildValue("OOOOO", (exc_typ ? exc_typ : Py_None),
    216 		(exc_val ? exc_val : Py_None), (exc_tb  ? exc_tb  : Py_None),
    217 		Py_None, obStringIO);
    218 	if (argsTB==NULL) {
    219 		log_err("pythonmod: cannot print exception, "
    220 			"cannot BuildValue for print_exception");
    221 		goto cleanup;
    222 	}
    223 
    224 	obResult = PyObject_CallObject(obFuncTB, argsTB);
    225 	if (obResult==NULL) {
    226 		PyErr_Print();
    227 		log_err("pythonmod: cannot print exception, "
    228 			"call traceback.print_exception() failed");
    229 		goto cleanup;
    230 	}
    231 
    232 	/* Now call the getvalue() method in the StringIO instance */
    233 	Py_DECREF(obFuncStringIO);
    234 	obFuncStringIO = PyObject_GetAttrString(obStringIO, "getvalue");
    235 	if (obFuncStringIO==NULL) {
    236 		log_err("pythonmod: cannot print exception, "
    237 			"cannot GetAttrString StringIO.getvalue");
    238 		goto cleanup;
    239 	}
    240 	Py_DECREF(obResult);
    241 	obResult = PyObject_CallObject(obFuncStringIO, NULL);
    242 	if (obResult==NULL) {
    243 		log_err("pythonmod: cannot print exception, "
    244 			"call StringIO.getvalue() failed");
    245 		goto cleanup;
    246 	}
    247 
    248 	/* And it should be a string all ready to go - duplicate it. */
    249 	if (!PyString_Check(obResult) && !PyUnicode_Check(obResult)) {
    250 		log_err("pythonmod: cannot print exception, "
    251 			"StringIO.getvalue() result did not String_Check"
    252 			" or Unicode_Check");
    253 		goto cleanup;
    254 	}
    255 	if(PyString_Check(obResult)) {
    256 		result = PyString_AsString(obResult);
    257 	} else {
    258 		ascstr = PyUnicode_AsASCIIString(obResult);
    259 		result = PyBytes_AsString(ascstr);
    260 	}
    261 	log_err("pythonmod: python error: %s", result);
    262 
    263 cleanup:
    264 	Py_XDECREF(modStringIO);
    265 	Py_XDECREF(modTB);
    266 	Py_XDECREF(obFuncStringIO);
    267 	Py_XDECREF(obStringIO);
    268 	Py_XDECREF(obFuncTB);
    269 	Py_XDECREF(argsTB);
    270 	Py_XDECREF(obResult);
    271 	Py_XDECREF(ascstr);
    272 
    273 	/* clear the exception, by not restoring it */
    274 	/* Restore the exception state */
    275 	/* PyErr_Restore(exc_typ, exc_val, exc_tb); */
    276 	/* when using PyErr_Restore there is no need to Py_XDECREF for
    277 	 * these 3 pointers. */
    278 	Py_XDECREF(exc_typ);
    279 	Py_XDECREF(exc_val);
    280 	Py_XDECREF(exc_tb);
    281 }
    282 
    283 /* we only want to unwind Python once at exit */
    284 static void
    285 pythonmod_atexit(void)
    286 {
    287    log_assert(py_mod_count == 0);
    288    log_assert(mainthr != NULL);
    289 
    290    PyEval_RestoreThread(mainthr);
    291    Py_Finalize();
    292 }
    293 
    294 int pythonmod_init(struct module_env* env, int id)
    295 {
    296    int py_mod_idx = py_mod_count++;
    297 
    298    /* Initialize module */
    299    FILE* script_py = NULL;
    300    PyObject* py_init_arg = NULL, *res = NULL, *fname = NULL;
    301    PyGILState_STATE gil;
    302    int init_standard = 1, i = 0;
    303 #if PY_MAJOR_VERSION < 3
    304    PyObject* PyFileObject = NULL;
    305 #endif
    306    struct config_strlist* cfg_item = env->cfg->python_script;
    307 
    308    struct pythonmod_env* pe = (struct pythonmod_env*)calloc(1, sizeof(struct pythonmod_env));
    309    if (!pe)
    310    {
    311       log_err("pythonmod: malloc failure");
    312       return 0;
    313    }
    314 
    315    env->modinfo[id] = (void*) pe;
    316 
    317    /* Initialize module */
    318    pe->fname=NULL; i = 0;
    319    while (cfg_item!=NULL) {
    320       if (py_mod_idx==i++) {
    321          pe->fname=cfg_item->str;
    322          break;
    323       }
    324       cfg_item = cfg_item->next;
    325    }
    326    if(pe->fname==NULL || pe->fname[0]==0) {
    327       log_err("pythonmod[%d]: no script given.", py_mod_idx);
    328       return 0;
    329    }
    330 
    331    /* Initialize Python libraries */
    332    if (py_mod_count==1 && !Py_IsInitialized())
    333    {
    334 #if PY_VERSION_HEX >= 0x03080000
    335       PyStatus status;
    336       PyPreConfig preconfig;
    337       PyConfig config;
    338 #endif
    339 #if PY_MAJOR_VERSION >= 3
    340       wchar_t progname[8];
    341       mbstowcs(progname, "unbound", 8);
    342 #else
    343       char *progname = "unbound";
    344 #endif
    345 #if PY_VERSION_HEX < 0x03080000
    346       Py_SetProgramName(progname);
    347 #else
    348       /* Python must be preinitialized, before the PyImport_AppendInittab
    349        * call. */
    350       PyPreConfig_InitPythonConfig(&preconfig);
    351       status = Py_PreInitialize(&preconfig);
    352       if(PyStatus_Exception(status)) {
    353 	log_err("python exception in Py_PreInitialize: %s%s%s",
    354 		(status.func?status.func:""), (status.func?": ":""),
    355 		(status.err_msg?status.err_msg:""));
    356 	return 0;
    357       }
    358 #endif
    359 #if PY_MAJOR_VERSION >= 3
    360       PyImport_AppendInittab(SWIG_name, (void*)SWIG_init);
    361 #endif
    362 #if PY_VERSION_HEX < 0x03080000
    363       Py_NoSiteFlag = 1;
    364       Py_Initialize();
    365 #else
    366       PyConfig_InitPythonConfig(&config);
    367       status = PyConfig_SetString(&config, &config.program_name, progname);
    368       if(PyStatus_Exception(status)) {
    369 	log_err("python exception in PyConfig_SetString(.. program_name ..): %s%s%s",
    370 		(status.func?status.func:""), (status.func?": ":""),
    371 		(status.err_msg?status.err_msg:""));
    372 	PyConfig_Clear(&config);
    373 	return 0;
    374       }
    375       config.site_import = 0;
    376       status = Py_InitializeFromConfig(&config);
    377       if(PyStatus_Exception(status)) {
    378 	log_err("python exception in Py_InitializeFromConfig: %s%s%s",
    379 		(status.func?status.func:""), (status.func?": ":""),
    380 		(status.err_msg?status.err_msg:""));
    381 	PyConfig_Clear(&config);
    382 	return 0;
    383       }
    384       PyConfig_Clear(&config);
    385 #endif
    386 #if PY_MAJOR_VERSION <= 2 || (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION <= 6)
    387       /* initthreads only for python 3.6 and older */
    388       PyEval_InitThreads();
    389 #endif
    390       SWIG_init();
    391       mainthr = PyEval_SaveThread();
    392 
    393       /* register callback to unwind Python at exit */
    394       atexit(pythonmod_atexit);
    395    }
    396 
    397    gil = PyGILState_Ensure();
    398 
    399    if (py_mod_count==1) {
    400       /* Initialize Python */
    401       if(PyRun_SimpleString("import sys \n") < 0 ) {
    402          log_err("pythonmod: cannot initialize core module: unboundmodule.py");
    403          goto python_init_fail;
    404       }
    405       PyRun_SimpleString("sys.path.append('.') \n");
    406       PyRun_SimpleString("sys.path.append('"RUN_DIR"') \n");
    407       PyRun_SimpleString("sys.path.append('"SHARE_DIR"') \n");
    408       if(env->cfg->directory && env->cfg->directory[0]) {
    409          char wdir[1524];
    410          snprintf(wdir, sizeof(wdir), "sys.path.append('%s') \n",
    411          env->cfg->directory);
    412          PyRun_SimpleString(wdir);
    413       }
    414       if(PyRun_SimpleString("import site\n") < 0) {
    415          log_err("pythonmod: cannot initialize core module: unboundmodule.py");
    416          goto python_init_fail;
    417       }
    418       if(PyRun_SimpleString("sys.path.extend(site.getsitepackages())\n") < 0) {
    419          log_err("pythonmod: cannot initialize core module: unboundmodule.py");
    420          goto python_init_fail;
    421       }
    422       if(PyRun_SimpleString("from unboundmodule import *\n") < 0)
    423       {
    424          log_err("pythonmod: cannot initialize core module: unboundmodule.py");
    425          goto python_init_fail;
    426       }
    427    }
    428 
    429    /* Check Python file load */
    430    /* uses python to open the file, this works on other platforms,
    431     * eg. Windows, to open the file in the correct mode for python */
    432 #if PY_MAJOR_VERSION < 3
    433    PyFileObject = PyFile_FromString((char*)pe->fname, "r");
    434    script_py = PyFile_AsFile(PyFileObject);
    435 #else
    436    script_py = fopen(pe->fname, "r");
    437 #endif
    438    if (script_py == NULL)
    439    {
    440       log_err("pythonmod: can't open file %s for reading", pe->fname);
    441       goto python_init_fail;
    442    }
    443 
    444    /* Load file */
    445    pe->module = PyImport_AddModule("__main__");
    446    Py_XINCREF(pe->module);
    447    pe->dict = PyModule_GetDict(pe->module);
    448    Py_XINCREF(pe->dict);
    449    clean_python_function_objects(pe->dict);
    450 
    451    pe->data = PyDict_New();
    452    /* add the script filename to the global "mod_env" for trivial access */
    453    fname = PyString_FromString(pe->fname);
    454    if(PyDict_SetItemString(pe->data, "script", fname) < 0) {
    455 	log_err("pythonmod: could not add item to dictionary");
    456 	Py_XDECREF(fname);
    457 	goto fail_close_file;
    458    }
    459    Py_XDECREF(fname);
    460    Py_XINCREF(pe->data);  /* reference will be stolen below */
    461    if(PyModule_AddObject(pe->module, "mod_env", pe->data) < 0) {
    462 	log_err("pythonmod: could not add mod_env object");
    463 	Py_XDECREF(pe->data);  /* 2 times, here and on python_init_fail; */
    464 	                       /* on failure the reference is not stolen */
    465 	goto fail_close_file;
    466    }
    467 
    468    if (PyRun_SimpleFile(script_py, pe->fname) < 0) {
    469 #if PY_MAJOR_VERSION <= 2 || (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION < 9)
    470       /* for python before 3.9 */
    471       log_err("pythonmod: can't parse Python script %s", pe->fname);
    472       /* print the error to logs too, run it again */
    473       fseek(script_py, 0, SEEK_SET);
    474       /* we don't run the file, like this, because then side-effects
    475        *    s = PyRun_File(script_py, pe->fname, Py_file_input,
    476        *        PyModule_GetDict(PyImport_AddModule("__main__")), pe->dict);
    477        * could happen (again). Instead we parse the file again to get
    478        * the error string in the logs, for when the daemon has stderr
    479        * removed.  SimpleFile run already printed to stderr, for then
    480        * this is called from unbound-checkconf or unbound -dd the user
    481        * has a nice formatted error.
    482       */
    483       /* ignore the NULL return of _node, it is NULL due to the parse failure
    484        * that we are expecting */
    485       (void)PyParser_SimpleParseFile(script_py, pe->fname, Py_file_input);
    486 #else
    487       /* for python 3.9 and newer */
    488       char* fstr = NULL;
    489       size_t flen = 0;
    490       long pos = 0;
    491       log_err("pythonmod: can't parse Python script %s", pe->fname);
    492       /* print the error to logs too, run it again */
    493       fseek(script_py, 0, SEEK_END);
    494       pos = ftell(script_py);
    495       if (pos == -1L) {
    496          log_err("ftell failed to print parse error: %s: %s",
    497             pe->fname, strerror(errno));
    498          goto fail_close_file;
    499       }
    500       flen = (size_t)pos;
    501 #ifdef SIZE_MAX
    502       if(flen > SIZE_MAX-2) {
    503 		log_err("script file too large");
    504 		goto fail_close_file;
    505       }
    506 #endif
    507       fstr = malloc(flen+1);
    508       if(!fstr) {
    509 		log_err("malloc failure to print parse error");
    510 		goto fail_close_file;
    511       }
    512       fseek(script_py, 0, SEEK_SET);
    513       if(fread(fstr, flen, 1, script_py) < 1) {
    514 		log_err("file read failed to print parse error: %s: %s",
    515 		pe->fname, strerror(errno));
    516 		free(fstr);
    517 		goto fail_close_file;
    518       }
    519       fstr[flen] = 0;
    520       /* we compile the string, but do not run it, to stop side-effects */
    521       /* ignore the NULL return of _node, it is NULL due to the parse failure
    522        * that we are expecting */
    523       (void)Py_CompileString(fstr, pe->fname, Py_file_input);
    524 #endif
    525 
    526       log_py_err();
    527 #if PY_MAJOR_VERSION <= 2 || (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION < 9)
    528       /* no cleanup needed for python before 3.9 */
    529 #else
    530       /* cleanup for python 3.9 and newer */
    531       free(fstr);
    532 #endif
    533       goto fail_close_file;
    534    }
    535 
    536 /* close the file */
    537 #if PY_MAJOR_VERSION < 3
    538    Py_XDECREF(PyFileObject);
    539 #else
    540    fclose(script_py);
    541 #endif
    542 
    543    if ((pe->func_init = PyDict_GetItemString(pe->dict, "init_standard")) == NULL)
    544    {
    545       init_standard = 0;
    546       if ((pe->func_init = PyDict_GetItemString(pe->dict, "init")) == NULL)
    547       {
    548          log_err("pythonmod: function init is missing in %s", pe->fname);
    549          goto python_init_fail;
    550       }
    551    }
    552    Py_XINCREF(pe->func_init);
    553    if ((pe->func_deinit = PyDict_GetItemString(pe->dict, "deinit")) == NULL)
    554    {
    555       log_err("pythonmod: function deinit is missing in %s", pe->fname);
    556       goto python_init_fail;
    557    }
    558    Py_XINCREF(pe->func_deinit);
    559    if ((pe->func_operate = PyDict_GetItemString(pe->dict, "operate")) == NULL)
    560    {
    561       log_err("pythonmod: function operate is missing in %s", pe->fname);
    562       goto python_init_fail;
    563    }
    564    Py_XINCREF(pe->func_operate);
    565    if ((pe->func_inform = PyDict_GetItemString(pe->dict, "inform_super")) == NULL)
    566    {
    567       log_err("pythonmod: function inform_super is missing in %s", pe->fname);
    568       goto python_init_fail;
    569    }
    570    Py_XINCREF(pe->func_inform);
    571 
    572    if (init_standard)
    573    {
    574       py_init_arg = SWIG_NewPointerObj((void*) env, SWIGTYPE_p_module_env, 0);
    575    }
    576    else
    577    {
    578       py_init_arg = SWIG_NewPointerObj((void*) env->cfg,
    579         SWIGTYPE_p_config_file, 0);
    580    }
    581    res = PyObject_CallFunction(pe->func_init, "iO", id, py_init_arg);
    582    if (PyErr_Occurred())
    583    {
    584       log_err("pythonmod: Exception occurred in function init");
    585       log_py_err();
    586       goto python_init_fail;
    587    }
    588 
    589    Py_XDECREF(res);
    590    Py_XDECREF(py_init_arg);
    591    PyGILState_Release(gil);
    592    return 1;
    593 
    594 fail_close_file:
    595 #if PY_MAJOR_VERSION < 3
    596    Py_XDECREF(PyFileObject);
    597 #else
    598    fclose(script_py);
    599 #endif
    600 
    601 python_init_fail:
    602    Py_XDECREF(pe->module);
    603    Py_XDECREF(pe->dict);
    604    Py_XDECREF(pe->data);
    605    Py_XDECREF(pe->func_init);
    606    Py_XDECREF(pe->func_deinit);
    607    Py_XDECREF(pe->func_operate);
    608    Py_XDECREF(pe->func_inform);
    609    Py_XDECREF(res);
    610    Py_XDECREF(py_init_arg);
    611    PyGILState_Release(gil);
    612    return 0;
    613 }
    614 
    615 void pythonmod_deinit(struct module_env* env, int id)
    616 {
    617    int cbtype;
    618    struct pythonmod_env* pe = env->modinfo[id];
    619    if(pe == NULL)
    620       return;
    621 
    622    /* Free Python resources */
    623    if(pe->module != NULL)
    624    {
    625       PyObject* res;
    626       PyGILState_STATE gil = PyGILState_Ensure();
    627 
    628       /* Deinit module */
    629       res = PyObject_CallFunction(pe->func_deinit, "i", id);
    630       if (PyErr_Occurred()) {
    631          log_err("pythonmod: Exception occurred in function deinit");
    632          log_py_err();
    633       }
    634       /* Free result if any */
    635       Py_XDECREF(res);
    636       /* Free shared data if any */
    637       Py_XDECREF(pe->module);
    638       Py_XDECREF(pe->dict);
    639       Py_XDECREF(pe->data);
    640       Py_XDECREF(pe->func_init);
    641       Py_XDECREF(pe->func_deinit);
    642       Py_XDECREF(pe->func_inform);
    643       Py_XDECREF(pe->func_operate);
    644       PyGILState_Release(gil);
    645 
    646       py_mod_count--;
    647    }
    648    pe->fname = NULL;
    649    free(pe);
    650 
    651    /* iterate over all possible callback types and clean up each in turn */
    652    for (cbtype = 0; cbtype < inplace_cb_types_total; cbtype++)
    653       inplace_cb_delete(env, cbtype, id);
    654 
    655    /* Module is deallocated in Python */
    656    env->modinfo[id] = NULL;
    657 }
    658 
    659 void pythonmod_inform_super(struct module_qstate* qstate, int id, struct module_qstate* super)
    660 {
    661    struct pythonmod_env* pe = (struct pythonmod_env*)qstate->env->modinfo[id];
    662    struct pythonmod_qstate* pq = (struct pythonmod_qstate*)qstate->minfo[id];
    663    PyObject* py_qstate, *py_sqstate, *res;
    664    PyGILState_STATE gil = PyGILState_Ensure();
    665 
    666    log_query_info(VERB_ALGO, "pythonmod: inform_super, sub is", &qstate->qinfo);
    667    log_query_info(VERB_ALGO, "super is", &super->qinfo);
    668 
    669    py_qstate = SWIG_NewPointerObj((void*) qstate, SWIGTYPE_p_module_qstate, 0);
    670    py_sqstate = SWIG_NewPointerObj((void*) super, SWIGTYPE_p_module_qstate, 0);
    671 
    672    res = PyObject_CallFunction(pe->func_inform, "iOOO", id, py_qstate,
    673 	py_sqstate, pq->data);
    674 
    675    if (PyErr_Occurred())
    676    {
    677       log_err("pythonmod: Exception occurred in function inform_super");
    678       log_py_err();
    679       qstate->ext_state[id] = module_error;
    680    }
    681    else if ((res == NULL)  || (!PyObject_IsTrue(res)))
    682    {
    683       log_err("pythonmod: python returned bad code in inform_super");
    684       qstate->ext_state[id] = module_error;
    685    }
    686 
    687    Py_XDECREF(res);
    688    Py_XDECREF(py_sqstate);
    689    Py_XDECREF(py_qstate);
    690 
    691    PyGILState_Release(gil);
    692 }
    693 
    694 void pythonmod_operate(struct module_qstate* qstate, enum module_ev event,
    695 	int id, struct outbound_entry* ATTR_UNUSED(outbound))
    696 {
    697    struct pythonmod_env* pe = (struct pythonmod_env*)qstate->env->modinfo[id];
    698    struct pythonmod_qstate* pq = (struct pythonmod_qstate*)qstate->minfo[id];
    699    PyObject* py_qstate, *res;
    700    PyGILState_STATE gil = PyGILState_Ensure();
    701 
    702    if ( pq == NULL)
    703    {
    704       /* create qstate */
    705       pq = qstate->minfo[id] = malloc(sizeof(struct pythonmod_qstate));
    706       if(!pq) {
    707 		log_err("pythonmod_operate: malloc failure for qstate");
    708 		PyGILState_Release(gil);
    709 		return;
    710       }
    711 
    712       /* Initialize per query data */
    713       pq->data = PyDict_New();
    714       if(!pq->data) {
    715 		log_err("pythonmod_operate: malloc failure for query data dict");
    716 		PyGILState_Release(gil);
    717 		return;
    718       }
    719    }
    720 
    721    /* Call operate */
    722    py_qstate = SWIG_NewPointerObj((void*) qstate, SWIGTYPE_p_module_qstate, 0);
    723    res = PyObject_CallFunction(pe->func_operate, "iiOO", id, (int) event,
    724 	py_qstate, pq->data);
    725    if (PyErr_Occurred())
    726    {
    727       log_err("pythonmod: Exception occurred in function operate, event: %s", strmodulevent(event));
    728       log_py_err();
    729       qstate->ext_state[id] = module_error;
    730    }
    731    else if ((res == NULL)  || (!PyObject_IsTrue(res)))
    732    {
    733       log_err("pythonmod: python returned bad code, event: %s", strmodulevent(event));
    734       qstate->ext_state[id] = module_error;
    735    }
    736    Py_XDECREF(res);
    737    Py_XDECREF(py_qstate);
    738 
    739    PyGILState_Release(gil);
    740 }
    741 
    742 void pythonmod_clear(struct module_qstate* qstate, int id)
    743 {
    744    struct pythonmod_qstate* pq;
    745    if (qstate == NULL)
    746       return;
    747 
    748    pq = (struct pythonmod_qstate*)qstate->minfo[id];
    749    verbose(VERB_ALGO, "pythonmod: clear, id: %d, pq:%p", id, pq);
    750    if(pq != NULL)
    751    {
    752       PyGILState_STATE gil = PyGILState_Ensure();
    753       Py_DECREF(pq->data);
    754       PyGILState_Release(gil);
    755       /* Free qstate */
    756       free(pq);
    757    }
    758 
    759    qstate->minfo[id] = NULL;
    760 }
    761 
    762 size_t pythonmod_get_mem(struct module_env* env, int id)
    763 {
    764    struct pythonmod_env* pe = (struct pythonmod_env*)env->modinfo[id];
    765    verbose(VERB_ALGO, "pythonmod: get_mem, id: %d, pe:%p", id, pe);
    766    if(!pe)
    767       return 0;
    768    return sizeof(*pe);
    769 }
    770 
    771 /**
    772  * The module function block
    773  */
    774 static struct module_func_block pythonmod_block = {
    775    "python",
    776    NULL, NULL, &pythonmod_init, &pythonmod_deinit, &pythonmod_operate,
    777    &pythonmod_inform_super, &pythonmod_clear, &pythonmod_get_mem
    778 };
    779 
    780 struct module_func_block* pythonmod_get_funcblock(void)
    781 {
    782    return &pythonmod_block;
    783 }
    784