2 * pythonmod.c: unbound module C wrapper
4 * Copyright (c) 2009, Zdenek Vasicek (vasicek AT fit.vutbr.cz)
5 * Marek Vavrusa (xvavru00 AT stud.fit.vutbr.cz)
7 * This software is open source.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
13 * * Redistributions of source code must retain the above copyright notice,
14 * this list of conditions and the following disclaimer.
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.
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.
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.
38 * Python module for unbound. Calls python script.
41 /* ignore the varargs unused warning from SWIGs internal vararg support */
43 #pragma GCC diagnostic ignored "-Wunused-parameter"
45 #pragma GCC diagnostic ignored "-Wunused-but-set-variable"
50 #include "sldns/sbuffer.h"
52 #undef _POSIX_C_SOURCE
56 #include "pythonmod/pythonmod.h"
57 #include "util/module.h"
58 #include "util/config_file.h"
59 #include "pythonmod_utils.h"
62 typedef struct PyObject PyObject
;
63 typedef struct PyThreadState PyThreadState
;
64 typedef void* PyGILState_STATE
;
68 * counter for python module instances
69 * incremented by pythonmod_init(...)
73 /** Python main thread */
74 PyThreadState
* mainthr
;
77 * Global state for the module.
79 struct pythonmod_env
{
81 /** Python script filename. */
87 /** Module init function */
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
;
96 /** Python dictionary. */
102 /** Module qstate. */
103 struct module_qstate
* qstate
;
107 * Per query state for the iterator module.
109 struct pythonmod_qstate
{
111 /** Module per query data. */
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.
126 clean_python_function_objects(PyObject
* dict
) {
127 const char* function_names
[] = {
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
]);
145 #include "pythonmod/interface.h"
148 /** log python error */
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
;
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
);
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");
177 if (modStringIO
==NULL
) {
179 modStringIO
= PyImport_ImportModule("io");
182 if (modStringIO
==NULL
) {
183 log_err("pythonmod: cannot print exception, "
184 "cannot ImportModule cStringIO or StringIO or io");
187 modTB
= PyImport_ImportModule("traceback");
189 log_err("pythonmod: cannot print exception, "
190 "cannot ImportModule traceback");
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
);
201 obStringIO
= PyObject_CallObject(obFuncStringIO
, NULL
);
202 if (obStringIO
==NULL
) {
203 log_err("pythonmod: cannot print exception, "
204 "cannot call %s.StringIO()", iomod
);
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");
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
);
219 log_err("pythonmod: cannot print exception, "
220 "cannot BuildValue for print_exception");
224 obResult
= PyObject_CallObject(obFuncTB
, argsTB
);
225 if (obResult
==NULL
) {
227 log_err("pythonmod: cannot print exception, "
228 "call traceback.print_exception() failed");
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");
241 obResult
= PyObject_CallObject(obFuncStringIO
, NULL
);
242 if (obResult
==NULL
) {
243 log_err("pythonmod: cannot print exception, "
244 "call StringIO.getvalue() failed");
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");
255 if(PyString_Check(obResult
)) {
256 result
= PyString_AsString(obResult
);
258 ascstr
= PyUnicode_AsASCIIString(obResult
);
259 result
= PyBytes_AsString(ascstr
);
261 log_err("pythonmod: python error: %s", result
);
264 Py_XDECREF(modStringIO
);
266 Py_XDECREF(obFuncStringIO
);
267 Py_XDECREF(obStringIO
);
268 Py_XDECREF(obFuncTB
);
270 Py_XDECREF(obResult
);
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. */
283 /* we only want to unwind Python once at exit */
285 pythonmod_atexit(void)
287 log_assert(py_mod_count
== 0);
288 log_assert(mainthr
!= NULL
);
290 PyEval_RestoreThread(mainthr
);
294 int pythonmod_init(struct module_env
* env
, int id
)
296 int py_mod_idx
= py_mod_count
++;
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
;
306 struct config_strlist
* cfg_item
= env
->cfg
->python_script
;
308 struct pythonmod_env
* pe
= (struct pythonmod_env
*)calloc(1, sizeof(struct pythonmod_env
));
311 log_err("pythonmod: malloc failure");
315 env
->modinfo
[id
] = (void*) pe
;
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
;
324 cfg_item
= cfg_item
->next
;
326 if(pe
->fname
==NULL
|| pe
->fname
[0]==0) {
327 log_err("pythonmod[%d]: no script given.", py_mod_idx
);
331 /* Initialize Python libraries */
332 if (py_mod_count
==1 && !Py_IsInitialized())
334 #if PY_VERSION_HEX >= 0x03080000
336 PyPreConfig preconfig
;
339 #if PY_MAJOR_VERSION >= 3
341 mbstowcs(progname
, "unbound", 8);
343 char *progname
= "unbound";
345 #if PY_VERSION_HEX < 0x03080000
346 Py_SetProgramName(progname
);
348 /* Python must be preinitialized, before the PyImport_AppendInittab
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
:""));
359 #if PY_MAJOR_VERSION >= 3
360 PyImport_AppendInittab(SWIG_name
, (void*)SWIG_init
);
362 #if PY_VERSION_HEX < 0x03080000
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
);
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
);
384 PyConfig_Clear(&config
);
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();
391 mainthr
= PyEval_SaveThread();
393 /* register callback to unwind Python at exit */
394 atexit(pythonmod_atexit
);
397 gil
= PyGILState_Ensure();
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
;
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]) {
410 snprintf(wdir
, sizeof(wdir
), "sys.path.append('%s') \n",
411 env
->cfg
->directory
);
412 PyRun_SimpleString(wdir
);
414 if(PyRun_SimpleString("import site\n") < 0) {
415 log_err("pythonmod: cannot initialize core module: unboundmodule.py");
416 goto python_init_fail
;
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
;
422 if(PyRun_SimpleString("from unboundmodule import *\n") < 0)
424 log_err("pythonmod: cannot initialize core module: unboundmodule.py");
425 goto python_init_fail
;
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
);
436 script_py
= fopen(pe
->fname
, "r");
438 if (script_py
== NULL
)
440 log_err("pythonmod: can't open file %s for reading", pe
->fname
);
441 goto python_init_fail
;
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
);
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");
457 goto python_init_fail
;
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 python_init_fail
;
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.
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
);
487 /* for python 3.9 and newer */
490 log_err("pythonmod: can't parse Python script %s", pe
->fname
);
491 /* print the error to logs too, run it again */
492 fseek(script_py
, 0, SEEK_END
);
493 flen
= (size_t)ftell(script_py
);
494 fstr
= malloc(flen
+1);
496 log_err("malloc failure to print parse error");
499 #if PY_MAJOR_VERSION < 3
500 Py_XDECREF(PyFileObject
);
505 goto python_init_fail
;
507 fseek(script_py
, 0, SEEK_SET
);
508 if(fread(fstr
, flen
, 1, script_py
) < 1) {
509 log_err("file read failed to print parse error: %s: %s",
510 pe
->fname
, strerror(errno
));
514 #if PY_MAJOR_VERSION < 3
515 Py_XDECREF(PyFileObject
);
520 goto python_init_fail
;
523 /* we compile the string, but do not run it, to stop side-effects */
524 /* ignore the NULL return of _node, it is NULL due to the parse failure
525 * that we are expecting */
526 (void)Py_CompileString(fstr
, pe
->fname
, Py_file_input
);
532 #if PY_MAJOR_VERSION < 3
533 Py_XDECREF(PyFileObject
);
538 #if PY_MAJOR_VERSION <= 2 || (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION < 9)
539 /* no cleanup needed for python before 3.9 */
541 /* cleanup for python 3.9 and newer */
544 goto python_init_fail
;
548 #if PY_MAJOR_VERSION < 3
549 Py_XDECREF(PyFileObject
);
554 if ((pe
->func_init
= PyDict_GetItemString(pe
->dict
, "init_standard")) == NULL
)
557 if ((pe
->func_init
= PyDict_GetItemString(pe
->dict
, "init")) == NULL
)
559 log_err("pythonmod: function init is missing in %s", pe
->fname
);
560 goto python_init_fail
;
563 Py_XINCREF(pe
->func_init
);
564 if ((pe
->func_deinit
= PyDict_GetItemString(pe
->dict
, "deinit")) == NULL
)
566 log_err("pythonmod: function deinit is missing in %s", pe
->fname
);
567 goto python_init_fail
;
569 Py_XINCREF(pe
->func_deinit
);
570 if ((pe
->func_operate
= PyDict_GetItemString(pe
->dict
, "operate")) == NULL
)
572 log_err("pythonmod: function operate is missing in %s", pe
->fname
);
573 goto python_init_fail
;
575 Py_XINCREF(pe
->func_operate
);
576 if ((pe
->func_inform
= PyDict_GetItemString(pe
->dict
, "inform_super")) == NULL
)
578 log_err("pythonmod: function inform_super is missing in %s", pe
->fname
);
579 goto python_init_fail
;
581 Py_XINCREF(pe
->func_inform
);
585 py_init_arg
= SWIG_NewPointerObj((void*) env
, SWIGTYPE_p_module_env
, 0);
589 py_init_arg
= SWIG_NewPointerObj((void*) env
->cfg
,
590 SWIGTYPE_p_config_file
, 0);
592 res
= PyObject_CallFunction(pe
->func_init
, "iO", id
, py_init_arg
);
593 if (PyErr_Occurred())
595 log_err("pythonmod: Exception occurred in function init");
597 goto python_init_fail
;
601 Py_XDECREF(py_init_arg
);
602 PyGILState_Release(gil
);
606 Py_XDECREF(pe
->module
);
607 Py_XDECREF(pe
->dict
);
608 Py_XDECREF(pe
->data
);
609 Py_XDECREF(pe
->func_init
);
610 Py_XDECREF(pe
->func_deinit
);
611 Py_XDECREF(pe
->func_operate
);
612 Py_XDECREF(pe
->func_inform
);
614 Py_XDECREF(py_init_arg
);
615 PyGILState_Release(gil
);
619 void pythonmod_deinit(struct module_env
* env
, int id
)
622 struct pythonmod_env
* pe
= env
->modinfo
[id
];
626 /* Free Python resources */
627 if(pe
->module
!= NULL
)
630 PyGILState_STATE gil
= PyGILState_Ensure();
633 res
= PyObject_CallFunction(pe
->func_deinit
, "i", id
);
634 if (PyErr_Occurred()) {
635 log_err("pythonmod: Exception occurred in function deinit");
638 /* Free result if any */
640 /* Free shared data if any */
641 Py_XDECREF(pe
->module
);
642 Py_XDECREF(pe
->dict
);
643 Py_XDECREF(pe
->data
);
644 Py_XDECREF(pe
->func_init
);
645 Py_XDECREF(pe
->func_deinit
);
646 Py_XDECREF(pe
->func_inform
);
647 Py_XDECREF(pe
->func_operate
);
648 PyGILState_Release(gil
);
655 /* iterate over all possible callback types and clean up each in turn */
656 for (cbtype
= 0; cbtype
< inplace_cb_types_total
; cbtype
++)
657 inplace_cb_delete(env
, cbtype
, id
);
659 /* Module is deallocated in Python */
660 env
->modinfo
[id
] = NULL
;
663 void pythonmod_inform_super(struct module_qstate
* qstate
, int id
, struct module_qstate
* super
)
665 struct pythonmod_env
* pe
= (struct pythonmod_env
*)qstate
->env
->modinfo
[id
];
666 struct pythonmod_qstate
* pq
= (struct pythonmod_qstate
*)qstate
->minfo
[id
];
667 PyObject
* py_qstate
, *py_sqstate
, *res
;
668 PyGILState_STATE gil
= PyGILState_Ensure();
670 log_query_info(VERB_ALGO
, "pythonmod: inform_super, sub is", &qstate
->qinfo
);
671 log_query_info(VERB_ALGO
, "super is", &super
->qinfo
);
673 py_qstate
= SWIG_NewPointerObj((void*) qstate
, SWIGTYPE_p_module_qstate
, 0);
674 py_sqstate
= SWIG_NewPointerObj((void*) super
, SWIGTYPE_p_module_qstate
, 0);
676 res
= PyObject_CallFunction(pe
->func_inform
, "iOOO", id
, py_qstate
,
677 py_sqstate
, pq
->data
);
679 if (PyErr_Occurred())
681 log_err("pythonmod: Exception occurred in function inform_super");
683 qstate
->ext_state
[id
] = module_error
;
685 else if ((res
== NULL
) || (!PyObject_IsTrue(res
)))
687 log_err("pythonmod: python returned bad code in inform_super");
688 qstate
->ext_state
[id
] = module_error
;
692 Py_XDECREF(py_sqstate
);
693 Py_XDECREF(py_qstate
);
695 PyGILState_Release(gil
);
698 void pythonmod_operate(struct module_qstate
* qstate
, enum module_ev event
,
699 int id
, struct outbound_entry
* ATTR_UNUSED(outbound
))
701 struct pythonmod_env
* pe
= (struct pythonmod_env
*)qstate
->env
->modinfo
[id
];
702 struct pythonmod_qstate
* pq
= (struct pythonmod_qstate
*)qstate
->minfo
[id
];
703 PyObject
* py_qstate
, *res
;
704 PyGILState_STATE gil
= PyGILState_Ensure();
709 pq
= qstate
->minfo
[id
] = malloc(sizeof(struct pythonmod_qstate
));
711 log_err("pythonmod_operate: malloc failure for qstate");
712 PyGILState_Release(gil
);
716 /* Initialize per query data */
717 pq
->data
= PyDict_New();
719 log_err("pythonmod_operate: malloc failure for query data dict");
720 PyGILState_Release(gil
);
726 py_qstate
= SWIG_NewPointerObj((void*) qstate
, SWIGTYPE_p_module_qstate
, 0);
727 res
= PyObject_CallFunction(pe
->func_operate
, "iiOO", id
, (int) event
,
728 py_qstate
, pq
->data
);
729 if (PyErr_Occurred())
731 log_err("pythonmod: Exception occurred in function operate, event: %s", strmodulevent(event
));
733 qstate
->ext_state
[id
] = module_error
;
735 else if ((res
== NULL
) || (!PyObject_IsTrue(res
)))
737 log_err("pythonmod: python returned bad code, event: %s", strmodulevent(event
));
738 qstate
->ext_state
[id
] = module_error
;
741 Py_XDECREF(py_qstate
);
743 PyGILState_Release(gil
);
746 void pythonmod_clear(struct module_qstate
* qstate
, int id
)
748 struct pythonmod_qstate
* pq
;
752 pq
= (struct pythonmod_qstate
*)qstate
->minfo
[id
];
753 verbose(VERB_ALGO
, "pythonmod: clear, id: %d, pq:%p", id
, pq
);
756 PyGILState_STATE gil
= PyGILState_Ensure();
758 PyGILState_Release(gil
);
763 qstate
->minfo
[id
] = NULL
;
766 size_t pythonmod_get_mem(struct module_env
* env
, int id
)
768 struct pythonmod_env
* pe
= (struct pythonmod_env
*)env
->modinfo
[id
];
769 verbose(VERB_ALGO
, "pythonmod: get_mem, id: %d, pe:%p", id
, pe
);
776 * The module function block
778 static struct module_func_block pythonmod_block
= {
780 &pythonmod_init
, &pythonmod_deinit
, &pythonmod_operate
, &pythonmod_inform_super
,
781 &pythonmod_clear
, &pythonmod_get_mem
784 struct module_func_block
* pythonmod_get_funcblock(void)
786 return &pythonmod_block
;