/* Its value is checked by setInputTensorDim */
}
+static int python_init_counter = 0;
+static PyThreadState *st = NULL;
+/**
+ * @brief Py_Initialize common wrapper for Python subplugins
+ * @note This prevents a python-using subplugin finalizing another subplugin's
+ * python interpreter by sharing the reference counter.
+ */
+void
+nnstreamer_python_init_refcnt ()
+{
+ if (!Py_IsInitialized ()) {
+ Py_Initialize ();
+ PyEval_InitThreads_IfGood ();
+ st = PyEval_SaveThread ();
+ }
+ python_init_counter++;
+}
+
+/**
+ * @brief Py_Finalize common wrapper for Python subplugins
+ * @note This prevents a python-using subplugin finalizing another subplugin's
+ * python interpreter by sharing the reference counter.
+ */
+void
+nnstreamer_python_fini_refcnt ()
+{
+ python_init_counter--;
+ if (python_init_counter == 0) {
+ /**
+ * @todo Python Finalize() is buggy and leaky.
+ * Do not call it until Python is fixed. (not fixed as in 2023-12)
+ * Calling Finalize at this state will leave modules randomly, which
+ * may cause assertion failure at exit.
+ PyEval_RestoreThread (st);
+ Py_Finalize ();
+ */
+ }
+}
+
+/**
+ * @brief Check Py_Init status for python eval functions.
+ * @return 0 if it's ready. negative error value if it's not ready.
+ */
+int
+nnstreamer_python_status_check ()
+{
+ if (python_init_counter == 0) {
+ fprintf (stderr, "nnstreamer_python_init_refcnt() is not called or it's already closed.");
+ return -EINVAL;
+ }
+
+ assert (Py_IsInitialized ());
+ return 0;
+}
+
#ifdef __cplusplus
} /* extern "C" */
#endif
extern int parseTensorsInfo (PyObject *result, GstTensorsInfo *info);
extern PyObject * PyTensorShape_New (PyObject * shape_cls, const GstTensorInfo *info);
+/**
+ * @brief Py_Initialize common wrapper for Python subplugins
+ * @note This prevents a python-using subplugin finalizing another subplugin's python interpreter by sharing the reference counter.
+ */
+extern void nnstreamer_python_init_refcnt ();
+
+/**
+ * @brief Py_Finalize common wrapper for Python subplugins
+ * @note This prevents a python-using subplugin finalizing another subplugin's python interpreter by sharing the reference counter.
+ */
+extern void nnstreamer_python_fini_refcnt ();
+
+/**
+ * @brief Check Py_Init status for python eval functions.
+ * @return 0 if it's ready. negative error value if it's not ready.
+ */
+extern int nnstreamer_python_status_check ();
+
#ifdef __cplusplus
} /* extern "C" */
#endif
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
-static PyThreadState *st;
/** @brief Initialize this object for tensor converter sub-plugin */
void
init_converter_py (void)
{
/** Python should be initialized and finalized only once */
- if (!Py_IsInitialized ()) {
- Py_Initialize ();
- }
- PyEval_InitThreads_IfGood ();
- st = PyEval_SaveThread ();
+ nnstreamer_python_init_refcnt ();
registerExternalConverter (&Python);
}
void
fini_converter_py (void)
{
- PyEval_RestoreThread (st);
+ nnstreamer_python_status_check ();
+ nnstreamer_python_fini_refcnt ();
unregisterExternalConverter (Python.name);
/**
* @todo Remove below lines after this issue is addressed.
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
-static PyThreadState *st;
/** @brief Initialize this object for tensordec-plugin */
void
init_decoder_py (void)
{
/** Python should be initialized and finalized only once */
- if (!Py_IsInitialized ())
- Py_Initialize ();
- PyEval_InitThreads_IfGood ();
- st = PyEval_SaveThread ();
-
+ nnstreamer_python_init_refcnt ();
nnstreamer_decoder_probe (&Python);
}
void
fini_decoder_py (void)
{
- PyEval_RestoreThread (st);
+ nnstreamer_python_status_check ();
+ nnstreamer_python_fini_refcnt ();
nnstreamer_decoder_exit (Python.modename);
/**
.allocateInInvoke = nullptr,
} } };
-static PyThreadState *st;
/** @brief Initialize this object for tensor_filter subplugin runtime register */
void
init_filter_py (void)
{
/** Python should be initialized and finalized only once */
- if (!Py_IsInitialized ())
- Py_Initialize ();
- PyEval_InitThreads_IfGood ();
- st = PyEval_SaveThread ();
-
+ nnstreamer_python_init_refcnt ();
nnstreamer_filter_probe (&NNS_support_python);
nnstreamer_filter_set_custom_property_desc (filter_subplugin_python, "${GENERAL_STRING}",
"There is no key-value pair defined by python3 subplugin. "
void
fini_filter_py (void)
{
- PyEval_RestoreThread (st);
+ nnstreamer_python_status_check ();
+ nnstreamer_python_fini_refcnt ();
nnstreamer_filter_exit (NNS_support_python.v0.name);
/**