From a9df45497dc79023ed1864dd9b8e435935220171 Mon Sep 17 00:00:00 2001 From: dnpwwo Date: Tue, 1 Mar 2022 13:09:01 +1100 Subject: [PATCH] BugFix: Linux crash when formating Python exceptions Other: Continue code cleanup --- hardware/plugins/Plugins.cpp | 45 +++++++++++------------------------- hardware/plugins/Plugins.h | 3 ++- main/EventsPythonModule.cpp | 6 ++--- 3 files changed, 18 insertions(+), 36 deletions(-) --- a/hardware/plugins/Plugins.cpp +++ b/hardware/plugins/Plugins.cpp @@ -724,13 +724,7 @@ namespace Plugins } else { - std::string sTypeText("Unknown"); - if (pExcept) - { - PyTypeObject* TypeName = (PyTypeObject*)pExcept; - PyNewRef pName = PyObject_GetAttrString((PyObject*)TypeName, "__name__"); - sTypeText = (std::string)pName; - } + std::string sTypeText("Unknown Error"); /* See if we can get a full traceback */ PyNewRef pModule = PyImport_ImportModule("traceback"); @@ -738,7 +732,7 @@ namespace Plugins { PyNewRef pFunc = PyObject_GetAttrString(pModule, "format_exception"); if (pFunc && PyCallable_Check(pFunc)) { - PyNewRef pList = PyObject_CallFunctionObjArgs(pFunc, pExcept, pValue, pTraceback, NULL); + PyNewRef pList = PyObject_CallFunctionObjArgs(pFunc, (PyObject*)pExcept, (PyObject*)pValue, (PyObject*)pTraceback, NULL); if (pList) { for (Py_ssize_t i = 0; i < PyList_Size(pList); i++) @@ -756,16 +750,19 @@ namespace Plugins } else { + if (pExcept) sTypeText = pExcept.Attribute("__name__"); Log(LOG_ERROR, "Exception: '%s'. No traceback available.", sTypeText.c_str()); } } else { + if (pExcept) sTypeText = pExcept.Attribute("__name__"); Log(LOG_ERROR, "'format_exception' lookup failed, exception: '%s'. No traceback available.", sTypeText.c_str()); } } else { + if (pExcept) sTypeText = pExcept.Attribute("__name__"); Log(LOG_ERROR, "'Traceback' module import failed, exception: '%s'. No traceback available.", sTypeText.c_str()); } } @@ -1950,7 +1947,7 @@ namespace Plugins } } - void CPlugin::Callback(PyObject *pTarget, const std::string &sHandler, PyObject *pParams) + void CPlugin::Callback(PyBorrowedRef& pTarget, const std::string &sHandler, PyObject *pParams) { try { @@ -1966,19 +1963,8 @@ namespace Plugins PyNewRef pFunc = PyObject_GetAttrString(pTarget, sHandler.c_str()); if (pFunc && PyCallable_Check(pFunc)) { - module_state *pModState = nullptr; - PyBorrowedRef brModule = PyState_FindModule(&DomoticzModuleDef); - if (!brModule) - { - brModule = PyState_FindModule(&DomoticzExModuleDef); - } - - if (brModule) - { - pModState = ((struct module_state *)PyModule_GetState(brModule)); - } - // Store the callback object so the Dump function has context if invoked + module_state* pModState = FindModule(); if (pModState) { pModState->lastCallback = pTarget; @@ -1986,14 +1972,12 @@ namespace Plugins if (m_bDebug & PDM_QUEUE) { - PyNewRef pName = PyObject_GetAttrString((PyObject*)(pTarget->ob_type), "__name__"); - if (pName) - Log(LOG_NORM, "Calling message handler '%s' on '%s' type object.", sHandler.c_str(), (std::string(pName).c_str())); + Log(LOG_NORM, "Calling message handler '%s' on '%s' type object.", sHandler.c_str(), pTarget.Type().c_str()); } PyErr_Clear(); - // Invokde the callback function + // Invoke the callback function PyNewRef pReturnValue = PyObject_CallObject(pFunc, pParams); if (pModState) @@ -2020,17 +2004,14 @@ namespace Plugins std::string sAttrName = pItem; if (sAttrName.substr(0, 2) != "__") // ignore system stuff { - if (PyObject_HasAttrString(pTarget, sAttrName.c_str())) + std::string strValue = pTarget.Attribute(sAttrName); + if (strValue.length()) { PyNewRef pValue = PyObject_GetAttrString(pTarget, sAttrName.c_str()); if (!PyCallable_Check(pValue)) // Filter out methods { - std::string strValue = pValue; - if (strValue.length()) - { - std::string sBlank((sAttrName.length() < 20) ? 20 - sAttrName.length() : 0, ' '); - Log(LOG_NORM, " ----> '%s'%s '%s'", sAttrName.c_str(), sBlank.c_str(), strValue.c_str()); - } + std::string sBlank((sAttrName.length() < 20) ? 20 - sAttrName.length() : 0, ' '); + Log(LOG_NORM, " ----> '%s'%s '%s'", sAttrName.c_str(), sBlank.c_str(), strValue.c_str()); } } } --- a/hardware/plugins/Plugins.h +++ b/hardware/plugins/Plugins.h @@ -92,7 +92,7 @@ namespace Plugins { void ConnectionWrite(CDirectiveBase *); void ConnectionDisconnect(CDirectiveBase *); void DisconnectEvent(CEventBase *); - void Callback(PyObject* pTarget, const std::string &sHandler, PyObject *pParams); + void Callback(PyBorrowedRef& pTarget, const std::string &sHandler, PyObject *pParams); void RestoreThread(); void ReleaseThread(); void Stop(); @@ -157,6 +157,7 @@ namespace Plugins { m_pObject = pObject; }; std::string Attribute(const char* name); + std::string Attribute(std::string& name) { return Attribute(name.c_str()); }; std::string Type(); bool IsDict() { return TypeCheck(Py_TPFLAGS_DICT_SUBCLASS); }; bool IsList() { return TypeCheck(Py_TPFLAGS_LIST_SUBCLASS); }; --- a/main/EventsPythonModule.cpp +++ b/main/EventsPythonModule.cpp @@ -297,7 +297,7 @@ namespace Plugins PyBorrowedRef pModule = PythonEventsGetModule(); if (pModule) { - PyBorrowedRef pModuleDict = Plugins::PyModule_GetDict(pModule); + PyBorrowedRef pModuleDict = PyModule_GetDict(pModule); if (!pModuleDict) { _log.Log(LOG_ERROR, "Python EventSystem: Failed to open module dictionary."); @@ -312,7 +312,7 @@ namespace Plugins return; } - PyNewRef pDeviceDict = Plugins::PyDict_New(); + PyNewRef pDeviceDict = PyDict_New(); if (PyDict_SetItemString(pModuleDict, "Devices", pDeviceDict) == -1) { _log.Log(LOG_ERROR, "Python EventSystem: Failed to add Device dictionary."); @@ -320,7 +320,7 @@ namespace Plugins return; } - if (PyType_Ready((PyTypeObject*)Plugins::PDeviceType) < 0) + if (PyType_Ready((PyTypeObject*)PDeviceType) < 0) { _log.Log(LOG_ERROR, "Python EventSystem: Unable to ready DeviceType Object."); PyEval_SaveThread();