569 lines
21 KiB
Diff
569 lines
21 KiB
Diff
From 5f61c5be95bb44f2ff3b913678c7bfdd3196ff69 Mon Sep 17 00:00:00 2001
|
|
From: dnpwwo <kendel.boul@gmail.com>
|
|
Date: Sun, 1 Jul 2018 13:29:03 +1000
|
|
Subject: [PATCH] Initial version working with Python 3.7
|
|
|
|
---
|
|
hardware/plugins/DelayedLink.h | 15 +++++++++++++++
|
|
hardware/plugins/PluginManager.cpp | 11 ++++++++++-
|
|
hardware/plugins/PluginManager.h | 5 +++--
|
|
hardware/plugins/PluginMessages.h | 3 +++
|
|
hardware/plugins/Plugins.cpp | 14 +++++++++++++-
|
|
hardware/plugins/Plugins.h | 1 +
|
|
main/EventsPythonModule.cpp | 24 +++++++++++++++++-------
|
|
7 files changed, 62 insertions(+), 11 deletions(-)
|
|
|
|
diff --git a/hardware/plugins/DelayedLink.h b/hardware/plugins/DelayedLink.h
|
|
index ecc7ec579..de9327a13 100644
|
|
--- a/hardware/plugins/DelayedLink.h
|
|
+++ b/hardware/plugins/DelayedLink.h
|
|
@@ -86,8 +86,13 @@ namespace Plugins {
|
|
DECLARE_PYTHON_SYMBOL(PyObject*, PyImport_ImportModule, const char*);
|
|
DECLARE_PYTHON_SYMBOL(PyObject*, PyObject_CallObject, PyObject* COMMA PyObject*);
|
|
DECLARE_PYTHON_SYMBOL(int, PyFrame_GetLineNumber, PyFrameObject*);
|
|
+ DECLARE_PYTHON_SYMBOL(void, PyEval_InitThreads, );
|
|
+ DECLARE_PYTHON_SYMBOL(PyThreadState*, PyThreadState_Get, );
|
|
DECLARE_PYTHON_SYMBOL(PyThreadState*, PyEval_SaveThread, void);
|
|
DECLARE_PYTHON_SYMBOL(void, PyEval_RestoreThread, PyThreadState*);
|
|
+ DECLARE_PYTHON_SYMBOL(void, PyEval_ReleaseLock, );
|
|
+ DECLARE_PYTHON_SYMBOL(PyThreadState*, PyThreadState_Swap, PyThreadState*);
|
|
+ DECLARE_PYTHON_SYMBOL(int, PyGILState_Check, );
|
|
DECLARE_PYTHON_SYMBOL(void, _Py_NegativeRefcount, const char* COMMA int COMMA PyObject*);
|
|
DECLARE_PYTHON_SYMBOL(PyObject*, _PyObject_New, PyTypeObject*);
|
|
#ifdef _DEBUG
|
|
@@ -197,8 +202,13 @@ namespace Plugins {
|
|
RESOLVE_PYTHON_SYMBOL(PyImport_ImportModule);
|
|
RESOLVE_PYTHON_SYMBOL(PyObject_CallObject);
|
|
RESOLVE_PYTHON_SYMBOL(PyFrame_GetLineNumber);
|
|
+ RESOLVE_PYTHON_SYMBOL(PyEval_InitThreads);
|
|
+ RESOLVE_PYTHON_SYMBOL(PyThreadState_Get);
|
|
RESOLVE_PYTHON_SYMBOL(PyEval_SaveThread);
|
|
RESOLVE_PYTHON_SYMBOL(PyEval_RestoreThread);
|
|
+ RESOLVE_PYTHON_SYMBOL(PyEval_ReleaseLock);
|
|
+ RESOLVE_PYTHON_SYMBOL(PyThreadState_Swap);
|
|
+ RESOLVE_PYTHON_SYMBOL(PyGILState_Check);
|
|
RESOLVE_PYTHON_SYMBOL(_Py_NegativeRefcount);
|
|
RESOLVE_PYTHON_SYMBOL(_PyObject_New);
|
|
#ifdef _DEBUG
|
|
@@ -365,8 +375,13 @@ extern SharedLibraryProxy* pythonLib;
|
|
#define PyImport_ImportModule pythonLib->PyImport_ImportModule
|
|
#define PyObject_CallObject pythonLib->PyObject_CallObject
|
|
#define PyFrame_GetLineNumber pythonLib->PyFrame_GetLineNumber
|
|
+#define PyEval_InitThreads pythonLib->PyEval_InitThreads
|
|
+#define PyThreadState_Get pythonLib->PyThreadState_Get
|
|
#define PyEval_SaveThread pythonLib->PyEval_SaveThread
|
|
#define PyEval_RestoreThread pythonLib->PyEval_RestoreThread
|
|
+#define PyEval_ReleaseLock pythonLib->PyEval_ReleaseLock
|
|
+#define PyThreadState_Swap pythonLib->PyThreadState_Swap
|
|
+#define PyGILState_Check pythonLib->PyGILState_Check
|
|
#define _Py_NegativeRefcount pythonLib->_Py_NegativeRefcount
|
|
#define _PyObject_New pythonLib->_PyObject_New
|
|
#define PyArg_ParseTuple pythonLib->PyArg_ParseTuple
|
|
diff --git a/hardware/plugins/PluginManager.cpp b/hardware/plugins/PluginManager.cpp
|
|
index 72c04575f..e896b8bcc 100644
|
|
--- a/hardware/plugins/PluginManager.cpp
|
|
+++ b/hardware/plugins/PluginManager.cpp
|
|
@@ -141,6 +141,9 @@ namespace Plugins {
|
|
Py_Initialize();
|
|
m_InitialPythonThread = PyEval_SaveThread();
|
|
|
|
+ // Initialise threads. Python 3.7+ does this inside Py_Initialize so done here for compatibility
|
|
+ PyEval_InitThreads();
|
|
+
|
|
m_bEnabled = true;
|
|
_log.Log(LOG_STATUS, "PluginSystem: Started, Python version '%s'.", sVersion.c_str());
|
|
}
|
|
@@ -319,7 +322,13 @@ namespace Plugins {
|
|
}
|
|
}
|
|
// Free the memory for the message
|
|
- if (Message) delete Message;
|
|
+ if (Message)
|
|
+ {
|
|
+ CPlugin* pPlugin = (CPlugin*)Message->Plugin();
|
|
+ pPlugin->RestoreThread();
|
|
+ delete Message;
|
|
+ pPlugin->ReleaseThread();
|
|
+ }
|
|
}
|
|
sleep_milliseconds(50);
|
|
}
|
|
diff --git a/hardware/plugins/PluginManager.h b/hardware/plugins/PluginManager.h
|
|
index 99e126e41..df66f63f6 100644
|
|
--- a/hardware/plugins/PluginManager.h
|
|
+++ b/hardware/plugins/PluginManager.h
|
|
@@ -36,10 +36,11 @@ namespace Plugins {
|
|
std::map<int, CDomoticzHardwareBase*>* GetHardware() { return &m_pPlugins; };
|
|
CDomoticzHardwareBase* RegisterPlugin(const int HwdID, const std::string &Name, const std::string &PluginKey);
|
|
void DeregisterPlugin(const int HwdID);
|
|
- bool StopPluginSystem();
|
|
- void AllPluginsStarted() { m_bAllPluginsStarted = true; };
|
|
+ bool StopPluginSystem();
|
|
+ void AllPluginsStarted() { m_bAllPluginsStarted = true; };
|
|
static void LoadSettings();
|
|
void DeviceModified(uint64_t ID);
|
|
+ void* PythonThread() { return m_InitialPythonThread; };
|
|
};
|
|
};
|
|
|
|
diff --git a/hardware/plugins/PluginMessages.h b/hardware/plugins/PluginMessages.h
|
|
index f4e902553..b254c969e 100644
|
|
--- a/hardware/plugins/PluginMessages.h
|
|
+++ b/hardware/plugins/PluginMessages.h
|
|
@@ -73,6 +73,7 @@ namespace Plugins {
|
|
boost::lock_guard<boost::mutex> l(PythonMutex);
|
|
m_pPlugin->RestoreThread();
|
|
ProcessLocked();
|
|
+ m_pPlugin->ReleaseThread();
|
|
};
|
|
virtual const char* PythonName() { return m_Callback.c_str(); };
|
|
};
|
|
@@ -367,6 +368,7 @@ static std::string get_utf8_from_ansi(const std::string &utf8, int codepage)
|
|
boost::lock_guard<boost::mutex> l(PythonMutex);
|
|
m_pPlugin->RestoreThread();
|
|
ProcessLocked();
|
|
+ m_pPlugin->ReleaseThread();
|
|
};
|
|
};
|
|
|
|
@@ -454,6 +456,7 @@ static std::string get_utf8_from_ansi(const std::string &utf8, int codepage)
|
|
boost::lock_guard<boost::mutex> l(PythonMutex);
|
|
m_pPlugin->RestoreThread();
|
|
ProcessLocked();
|
|
+ m_pPlugin->ReleaseThread();
|
|
}
|
|
};
|
|
|
|
diff --git a/hardware/plugins/Plugins.cpp b/hardware/plugins/Plugins.cpp
|
|
index 329080b0a..9647a8c91 100644
|
|
--- a/hardware/plugins/Plugins.cpp
|
|
+++ b/hardware/plugins/Plugins.cpp
|
|
@@ -35,6 +35,7 @@ extern std::string szWWWFolder;
|
|
extern std::string szAppVersion;
|
|
extern std::string szAppHash;
|
|
extern std::string szAppDate;
|
|
+extern MainWorker m_mainworker;
|
|
|
|
namespace Plugins {
|
|
|
|
@@ -867,6 +868,7 @@ namespace Plugins {
|
|
|
|
try
|
|
{
|
|
+ PyEval_RestoreThread((PyThreadState*)m_mainworker.m_pluginsystem.PythonThread());
|
|
m_PyInterpreter = Py_NewInterpreter();
|
|
if (!m_PyInterpreter)
|
|
{
|
|
@@ -973,6 +975,7 @@ namespace Plugins {
|
|
}
|
|
_log.Log(LOG_STATUS, "(%s) Initialized %s", Name.c_str(), sExtraDetail.c_str());
|
|
|
|
+ PyEval_SaveThread();
|
|
return true;
|
|
}
|
|
catch (...)
|
|
@@ -981,6 +984,7 @@ namespace Plugins {
|
|
}
|
|
|
|
Error:
|
|
+ PyEval_SaveThread();
|
|
m_bIsStarting = false;
|
|
return false;
|
|
}
|
|
@@ -1488,7 +1492,14 @@ namespace Plugins {
|
|
|
|
void CPlugin::RestoreThread()
|
|
{
|
|
- if (m_PyInterpreter) PyEval_RestoreThread((PyThreadState*)m_PyInterpreter);
|
|
+ if (m_PyInterpreter)
|
|
+ PyEval_RestoreThread((PyThreadState*)m_PyInterpreter);
|
|
+ }
|
|
+
|
|
+ void CPlugin::ReleaseThread()
|
|
+ {
|
|
+ if (m_PyInterpreter)
|
|
+ PyEval_SaveThread();
|
|
}
|
|
|
|
void CPlugin::Callback(std::string sHandler, void * pParams)
|
|
@@ -1537,6 +1548,7 @@ namespace Plugins {
|
|
if (m_SettingsDict) Py_XDECREF(m_SettingsDict);
|
|
if (m_PyInterpreter) Py_EndInterpreter((PyThreadState*)m_PyInterpreter);
|
|
Py_XDECREF(m_PyModule);
|
|
+ PyEval_ReleaseLock();
|
|
}
|
|
catch (std::exception *e)
|
|
{
|
|
diff --git a/hardware/plugins/Plugins.h b/hardware/plugins/Plugins.h
|
|
index 0145747ee..d8808e147 100644
|
|
--- a/hardware/plugins/Plugins.h
|
|
+++ b/hardware/plugins/Plugins.h
|
|
@@ -78,6 +78,7 @@ namespace Plugins {
|
|
void DisconnectEvent(CEventBase*);
|
|
void Callback(std::string sHandler, void* pParams);
|
|
void RestoreThread();
|
|
+ void ReleaseThread();
|
|
void Stop();
|
|
|
|
void WriteDebugBuffer(const std::vector<byte>& Buffer, bool Incoming);
|
|
diff --git a/main/EventsPythonModule.cpp b/main/EventsPythonModule.cpp
|
|
index a839cb546..bdde645a9 100644
|
|
--- a/main/EventsPythonModule.cpp
|
|
+++ b/main/EventsPythonModule.cpp
|
|
@@ -122,6 +122,7 @@
|
|
}
|
|
|
|
boost::lock_guard<boost::mutex> l(PythonMutex);
|
|
+ PyEval_RestoreThread((PyThreadState*)m_mainworker.m_pluginsystem.PythonThread());
|
|
m_PyInterpreter = Py_NewInterpreter();
|
|
if (!m_PyInterpreter)
|
|
{
|
|
@@ -144,7 +145,8 @@
|
|
PythonEventsInitalized = 1;
|
|
|
|
PyObject* pModule = Plugins::PythonEventsGetModule();
|
|
- if (!pModule) {
|
|
+ PyEval_SaveThread();
|
|
+ if (!pModule) {
|
|
_log.Log(LOG_ERROR, "EventSystem - Python: Failed to initialize module.");
|
|
return false;
|
|
}
|
|
@@ -159,7 +161,8 @@
|
|
if (Plugins::Py_IsInitialized())
|
|
Py_EndInterpreter((PyThreadState*)m_PyInterpreter);
|
|
m_PyInterpreter = NULL;
|
|
- _log.Log(LOG_STATUS, "EventSystem - Python stopped...");
|
|
+ PyEval_ReleaseLock();
|
|
+ _log.Log(LOG_STATUS, "EventSystem - Python stopped...");
|
|
return true;
|
|
} else
|
|
return false;
|
|
@@ -217,7 +220,8 @@
|
|
|
|
if (!pModuleDict) {
|
|
_log.Log(LOG_ERROR, "Python EventSystem: Failed to open module dictionary.");
|
|
- return;
|
|
+ PyEval_SaveThread();
|
|
+ return;
|
|
}
|
|
|
|
if (Plugins::PyDict_SetItemString(pModuleDict, "changed_device_name", Plugins::PyUnicode_FromString(m_devicestates[DeviceID].deviceName.c_str())) == -1) {
|
|
@@ -230,13 +234,15 @@
|
|
if (Plugins::PyDict_SetItemString(pModuleDict, "Devices", (PyObject*)m_DeviceDict) == -1)
|
|
{
|
|
_log.Log(LOG_ERROR, "Python EventSystem: Failed to add Device dictionary.");
|
|
- return;
|
|
+ PyEval_SaveThread();
|
|
+ return;
|
|
}
|
|
Py_DECREF(m_DeviceDict);
|
|
|
|
if (Plugins::PyType_Ready(&Plugins::PDeviceType) < 0) {
|
|
_log.Log(LOG_ERROR, "Python EventSystem: Unable to ready DeviceType Object.");
|
|
- return;
|
|
+ PyEval_SaveThread();
|
|
+ return;
|
|
}
|
|
|
|
// Mutex
|
|
@@ -332,7 +338,8 @@
|
|
if (Plugins::PyDict_SetItemString(pModuleDict, "user_variables", (PyObject*)m_uservariablesDict) == -1)
|
|
{
|
|
_log.Log(LOG_ERROR, "Python EventSystem: Failed to add uservariables dictionary.");
|
|
- return;
|
|
+ PyEval_SaveThread();
|
|
+ return;
|
|
}
|
|
Py_DECREF(m_uservariablesDict);
|
|
|
|
@@ -401,7 +408,10 @@
|
|
} else {
|
|
_log.Log(LOG_ERROR, "Python EventSystem: Module not available to events");
|
|
}
|
|
- } else {
|
|
+
|
|
+ PyEval_SaveThread();
|
|
+
|
|
+ } else {
|
|
_log.Log(LOG_ERROR, "EventSystem: Python not initalized");
|
|
}
|
|
|
|
From 64750ee9d6b9388d0d4c48f32679b2fb52bb9931 Mon Sep 17 00:00:00 2001
|
|
From: dnpwwo <kendel.boul@gmail.com>
|
|
Date: Sun, 1 Jul 2018 20:29:24 +1000
|
|
Subject: [PATCH] 1st level Python tracing added
|
|
|
|
---
|
|
hardware/plugins/DelayedLink.h | 6 ++
|
|
hardware/plugins/Plugins.cpp | 133 +++++++++++++++++++++++++++++++++
|
|
hardware/plugins/Plugins.h | 1 +
|
|
3 files changed, 140 insertions(+)
|
|
|
|
diff --git a/hardware/plugins/DelayedLink.h b/hardware/plugins/DelayedLink.h
|
|
index de9327a13..bdb9d0ec3 100644
|
|
--- a/hardware/plugins/DelayedLink.h
|
|
+++ b/hardware/plugins/DelayedLink.h
|
|
@@ -119,6 +119,8 @@ namespace Plugins {
|
|
DECLARE_PYTHON_SYMBOL(long, PyLong_AsLong, PyObject*);
|
|
DECLARE_PYTHON_SYMBOL(PyObject*, PyUnicode_AsUTF8String, PyObject*);
|
|
DECLARE_PYTHON_SYMBOL(PyObject*, PyImport_AddModule, const char*);
|
|
+ DECLARE_PYTHON_SYMBOL(void, PyEval_SetProfile, Py_tracefunc COMMA PyObject*);
|
|
+ DECLARE_PYTHON_SYMBOL(void, PyEval_SetTrace, Py_tracefunc COMMA PyObject*);
|
|
|
|
#ifdef _DEBUG
|
|
// In a debug build dealloc is a function but for release builds its a macro
|
|
@@ -238,6 +240,8 @@ namespace Plugins {
|
|
RESOLVE_PYTHON_SYMBOL(PyLong_AsLong);
|
|
RESOLVE_PYTHON_SYMBOL(PyUnicode_AsUTF8String);
|
|
RESOLVE_PYTHON_SYMBOL(PyImport_AddModule);
|
|
+ RESOLVE_PYTHON_SYMBOL(PyEval_SetProfile);
|
|
+ RESOLVE_PYTHON_SYMBOL(PyEval_SetTrace);
|
|
}
|
|
}
|
|
_Py_NoneStruct.ob_refcnt = 1;
|
|
@@ -414,4 +418,6 @@ extern SharedLibraryProxy* pythonLib;
|
|
#define PyLong_AsLong pythonLib->PyLong_AsLong
|
|
#define PyUnicode_AsUTF8String pythonLib->PyUnicode_AsUTF8String
|
|
#define PyImport_AddModule pythonLib->PyImport_AddModule
|
|
+#define PyEval_SetProfile pythonLib->PyEval_SetProfile
|
|
+#define PyEval_SetTrace pythonLib->PyEval_SetTrace
|
|
}
|
|
diff --git a/hardware/plugins/Plugins.cpp b/hardware/plugins/Plugins.cpp
|
|
index 9647a8c91..05ef29b97 100644
|
|
--- a/hardware/plugins/Plugins.cpp
|
|
+++ b/hardware/plugins/Plugins.cpp
|
|
@@ -120,6 +120,96 @@ namespace Plugins {
|
|
if (pTraceback) Py_XDECREF(pTraceback);
|
|
}
|
|
|
|
+ int PyDomoticz_ProfileFunc(PyObject *self, PyFrameObject *frame, int what, PyObject *arg)
|
|
+ {
|
|
+ module_state* pModState = ((struct module_state*)PyModule_GetState(self));
|
|
+ if (!pModState)
|
|
+ {
|
|
+ _log.Log(LOG_ERROR, "CPlugin:%s, unable to obtain module state.", __func__);
|
|
+ }
|
|
+ else if (!pModState->pPlugin)
|
|
+ {
|
|
+ _log.Log(LOG_ERROR, "CPlugin:%s, illegal operation, Plugin has not started yet.", __func__);
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ int lineno = PyFrame_GetLineNumber(frame);
|
|
+ std::string sFuncName = "Unknown";
|
|
+ PyCodeObject* pCode = frame->f_code;
|
|
+ if (pCode && pCode->co_filename)
|
|
+ {
|
|
+ PyBytesObject* pFileBytes = (PyBytesObject*)PyUnicode_AsASCIIString(pCode->co_filename);
|
|
+ sFuncName = pFileBytes->ob_sval;
|
|
+ }
|
|
+ if (pCode && pCode->co_name)
|
|
+ {
|
|
+ if (sFuncName.length()) sFuncName += "\\";
|
|
+ PyBytesObject* pFuncBytes = (PyBytesObject*)PyUnicode_AsASCIIString(pCode->co_name);
|
|
+ sFuncName = pFuncBytes->ob_sval;
|
|
+ }
|
|
+
|
|
+ switch (what)
|
|
+ {
|
|
+ case PyTrace_CALL:
|
|
+ _log.Log(LOG_NORM, "(%s) Calling function at line %d in '%s'", pModState->pPlugin->Name.c_str(), lineno, sFuncName.c_str());
|
|
+ break;
|
|
+ case PyTrace_RETURN:
|
|
+ _log.Log(LOG_NORM, "(%s) Returning from line %d in '%s'", pModState->pPlugin->Name.c_str(), lineno, sFuncName.c_str());
|
|
+ break;
|
|
+ case PyTrace_EXCEPTION:
|
|
+ _log.Log(LOG_NORM, "(%s) Exception at line %d in '%s'", pModState->pPlugin->Name.c_str(), lineno, sFuncName.c_str());
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ int PyDomoticz_TraceFunc(PyObject *self, PyFrameObject *frame, int what, PyObject *arg)
|
|
+ {
|
|
+ module_state* pModState = ((struct module_state*)PyModule_GetState(self));
|
|
+ if (!pModState)
|
|
+ {
|
|
+ _log.Log(LOG_ERROR, "CPlugin:%s, unable to obtain module state.", __func__);
|
|
+ }
|
|
+ else if (!pModState->pPlugin)
|
|
+ {
|
|
+ _log.Log(LOG_ERROR, "CPlugin:%s, illegal operation, Plugin has not started yet.", __func__);
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ int lineno = PyFrame_GetLineNumber(frame);
|
|
+ std::string sFuncName = "Unknown";
|
|
+ PyCodeObject* pCode = frame->f_code;
|
|
+ if (pCode && pCode->co_filename)
|
|
+ {
|
|
+ PyBytesObject* pFileBytes = (PyBytesObject*)PyUnicode_AsASCIIString(pCode->co_filename);
|
|
+ sFuncName = pFileBytes->ob_sval;
|
|
+ }
|
|
+ if (pCode && pCode->co_name)
|
|
+ {
|
|
+ if (sFuncName.length()) sFuncName += "\\";
|
|
+ PyBytesObject* pFuncBytes = (PyBytesObject*)PyUnicode_AsASCIIString(pCode->co_name);
|
|
+ sFuncName = pFuncBytes->ob_sval;
|
|
+ }
|
|
+
|
|
+ switch (what)
|
|
+ {
|
|
+ case PyTrace_CALL:
|
|
+ _log.Log(LOG_NORM, "(%s) Calling function at line %d in '%s'", pModState->pPlugin->Name.c_str(), lineno, sFuncName.c_str());
|
|
+ break;
|
|
+ case PyTrace_LINE:
|
|
+ _log.Log(LOG_NORM, "(%s) Executing line %d in '%s'", pModState->pPlugin->Name.c_str(), lineno, sFuncName.c_str());
|
|
+ break;
|
|
+ case PyTrace_EXCEPTION:
|
|
+ _log.Log(LOG_NORM, "(%s) Exception at line %d in '%s'", pModState->pPlugin->Name.c_str(), lineno, sFuncName.c_str());
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
static PyObject* PyDomoticz_Debug(PyObject *self, PyObject *args)
|
|
{
|
|
module_state* pModState = ((struct module_state*)PyModule_GetState(self));
|
|
@@ -355,6 +445,47 @@ namespace Plugins {
|
|
return Py_None;
|
|
}
|
|
|
|
+ static PyObject* PyDomoticz_Trace(PyObject *self, PyObject *args)
|
|
+ {
|
|
+ module_state* pModState = ((struct module_state*)PyModule_GetState(self));
|
|
+ if (!pModState)
|
|
+ {
|
|
+ _log.Log(LOG_ERROR, "CPlugin:%s, unable to obtain module state.", __func__);
|
|
+ }
|
|
+ else if (!pModState->pPlugin)
|
|
+ {
|
|
+ _log.Log(LOG_ERROR, "CPlugin:%s, illegal operation, Plugin has not started yet.", __func__);
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ int bTrace = 0;
|
|
+ if (!PyArg_ParseTuple(args, "p", &bTrace))
|
|
+ {
|
|
+ _log.Log(LOG_ERROR, "(%s) failed to parse parameter, True/False expected.", pModState->pPlugin->Name.c_str());
|
|
+ LogPythonException(pModState->pPlugin, std::string(__func__));
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ pModState->pPlugin->m_bTracing = (bool)bTrace;
|
|
+ _log.Log(LOG_NORM, "(%s) Low level Python tracing %s.", pModState->pPlugin->Name.c_str(), (pModState->pPlugin->m_bTracing ? "ENABLED" : "DISABLED"));
|
|
+
|
|
+ if (pModState->pPlugin->m_bTracing)
|
|
+ {
|
|
+ PyEval_SetProfile(PyDomoticz_ProfileFunc, self);
|
|
+ PyEval_SetTrace(PyDomoticz_TraceFunc, self);
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ PyEval_SetProfile(NULL, NULL);
|
|
+ PyEval_SetTrace(NULL, NULL);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ Py_INCREF(Py_None);
|
|
+ return Py_None;
|
|
+ }
|
|
+
|
|
static PyMethodDef DomoticzMethods[] = {
|
|
{ "Debug", PyDomoticz_Debug, METH_VARARGS, "Write a message to Domoticz log only if verbose logging is turned on." },
|
|
{ "Log", PyDomoticz_Log, METH_VARARGS, "Write a message to Domoticz log." },
|
|
@@ -363,6 +494,7 @@ namespace Plugins {
|
|
{ "Debugging", PyDomoticz_Debugging, METH_VARARGS, "Set logging level. 1 set verbose logging, all other values use default level" },
|
|
{ "Heartbeat", PyDomoticz_Heartbeat, METH_VARARGS, "Set the heartbeat interval, default 10 seconds." },
|
|
{ "Notifier", PyDomoticz_Notifier, METH_VARARGS, "Enable notification handling with supplied name." },
|
|
+ { "Trace", PyDomoticz_Trace, METH_VARARGS, "Enable/Disable line level Python tracing." },
|
|
{ NULL, NULL, 0, NULL }
|
|
};
|
|
|
|
@@ -439,6 +571,7 @@ namespace Plugins {
|
|
Name = sName;
|
|
m_bIsStarted = false;
|
|
m_bIsStarting = false;
|
|
+ m_bTracing = false;
|
|
}
|
|
|
|
CPlugin::~CPlugin(void)
|
|
diff --git a/hardware/plugins/Plugins.h b/hardware/plugins/Plugins.h
|
|
index d8808e147..d184e2be3 100644
|
|
--- a/hardware/plugins/Plugins.h
|
|
+++ b/hardware/plugins/Plugins.h
|
|
@@ -108,6 +108,7 @@ namespace Plugins {
|
|
PluginDebugMask m_bDebug;
|
|
bool m_stoprequested;
|
|
bool m_bIsStarting;
|
|
+ bool m_bTracing;
|
|
};
|
|
|
|
class CPluginNotifier : public CNotificationBase
|
|
|
|
From 463bb8e28be5ec7a6cfc452a5318f89f2d65a14d Mon Sep 17 00:00:00 2001
|
|
From: dnpwwo <kendel.boul@gmail.com>
|
|
Date: Sun, 1 Jul 2018 22:56:32 +1000
|
|
Subject: [PATCH] 2nd version, Python 3.7 and 3.6
|
|
|
|
---
|
|
hardware/plugins/DelayedLink.h | 3 +++
|
|
hardware/plugins/PluginManager.cpp | 8 ++++++--
|
|
2 files changed, 9 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/hardware/plugins/DelayedLink.h b/hardware/plugins/DelayedLink.h
|
|
index bdb9d0ec3..44bcb118e 100644
|
|
--- a/hardware/plugins/DelayedLink.h
|
|
+++ b/hardware/plugins/DelayedLink.h
|
|
@@ -87,6 +87,7 @@ namespace Plugins {
|
|
DECLARE_PYTHON_SYMBOL(PyObject*, PyObject_CallObject, PyObject* COMMA PyObject*);
|
|
DECLARE_PYTHON_SYMBOL(int, PyFrame_GetLineNumber, PyFrameObject*);
|
|
DECLARE_PYTHON_SYMBOL(void, PyEval_InitThreads, );
|
|
+ DECLARE_PYTHON_SYMBOL(int, PyEval_ThreadsInitialized, );
|
|
DECLARE_PYTHON_SYMBOL(PyThreadState*, PyThreadState_Get, );
|
|
DECLARE_PYTHON_SYMBOL(PyThreadState*, PyEval_SaveThread, void);
|
|
DECLARE_PYTHON_SYMBOL(void, PyEval_RestoreThread, PyThreadState*);
|
|
@@ -205,6 +206,7 @@ namespace Plugins {
|
|
RESOLVE_PYTHON_SYMBOL(PyObject_CallObject);
|
|
RESOLVE_PYTHON_SYMBOL(PyFrame_GetLineNumber);
|
|
RESOLVE_PYTHON_SYMBOL(PyEval_InitThreads);
|
|
+ RESOLVE_PYTHON_SYMBOL(PyEval_ThreadsInitialized);
|
|
RESOLVE_PYTHON_SYMBOL(PyThreadState_Get);
|
|
RESOLVE_PYTHON_SYMBOL(PyEval_SaveThread);
|
|
RESOLVE_PYTHON_SYMBOL(PyEval_RestoreThread);
|
|
@@ -380,6 +382,7 @@ extern SharedLibraryProxy* pythonLib;
|
|
#define PyObject_CallObject pythonLib->PyObject_CallObject
|
|
#define PyFrame_GetLineNumber pythonLib->PyFrame_GetLineNumber
|
|
#define PyEval_InitThreads pythonLib->PyEval_InitThreads
|
|
+#define PyEval_ThreadsInitialized pythonLib->PyEval_ThreadsInitialized
|
|
#define PyThreadState_Get pythonLib->PyThreadState_Get
|
|
#define PyEval_SaveThread pythonLib->PyEval_SaveThread
|
|
#define PyEval_RestoreThread pythonLib->PyEval_RestoreThread
|
|
diff --git a/hardware/plugins/PluginManager.cpp b/hardware/plugins/PluginManager.cpp
|
|
index e896b8bcc..32fa2bffd 100644
|
|
--- a/hardware/plugins/PluginManager.cpp
|
|
+++ b/hardware/plugins/PluginManager.cpp
|
|
@@ -139,10 +139,14 @@ namespace Plugins {
|
|
}
|
|
|
|
Py_Initialize();
|
|
- m_InitialPythonThread = PyEval_SaveThread();
|
|
|
|
// Initialise threads. Python 3.7+ does this inside Py_Initialize so done here for compatibility
|
|
- PyEval_InitThreads();
|
|
+ if (!PyEval_ThreadsInitialized())
|
|
+ {
|
|
+ PyEval_InitThreads();
|
|
+ }
|
|
+
|
|
+ m_InitialPythonThread = PyEval_SaveThread();
|
|
|
|
m_bEnabled = true;
|
|
_log.Log(LOG_STATUS, "PluginSystem: Started, Python version '%s'.", sVersion.c_str());
|
|
|