diff --git a/libnymea-core/integrations/python/pything.h b/libnymea-core/integrations/python/pything.h index 6fb48701..5118a44a 100644 --- a/libnymea-core/integrations/python/pything.h +++ b/libnymea-core/integrations/python/pything.h @@ -44,6 +44,7 @@ static PyObject* PyThing_new(PyTypeObject *type, PyObject */*args*/, PyObject */ if (self == NULL) { return nullptr; } + qWarning() << "*creating pyThing" << self; self->mutex = new QMutex(); return (PyObject*)self; @@ -86,6 +87,7 @@ static void PyThing_setThing(PyThing *self, Thing *thing) static void PyThing_dealloc(PyThing * self) { + qWarning() << "destryoing pything" << self; Py_XDECREF(self->name); Py_XDECREF(self->id); Py_XDECREF(self->thingClassId); @@ -213,7 +215,6 @@ static PyMethodDef PyThing_methods[] = { }; static PyMemberDef PyThing_members[] = { - {"nameChangedHandler", T_OBJECT_EX, offsetof(PyThing, nameChangedHandler), READONLY, "Set a callback for when the thing name changes"}, {"nameChangedHandler", T_OBJECT_EX, offsetof(PyThing, nameChangedHandler), 0, "Set a callback for when the thing name changes"}, {nullptr, 0, 0, 0, nullptr} /* Sentinel */ }; diff --git a/libnymea-core/integrations/pythonintegrationplugin.cpp b/libnymea-core/integrations/pythonintegrationplugin.cpp index 027beeb0..6e019619 100644 --- a/libnymea-core/integrations/pythonintegrationplugin.cpp +++ b/libnymea-core/integrations/pythonintegrationplugin.cpp @@ -43,8 +43,9 @@ PyObject* nymea_flush(PyObject* /*self*/, PyObject* /*args*/) Py_RETURN_NONE; } -PyObject* task_done(PyObject* /*self*/, PyObject* args) +PyObject* PythonIntegrationPlugin::task_done(PyObject* self, PyObject* args) { + Q_UNUSED(self) PyObject *result = nullptr; @@ -63,8 +64,9 @@ PyObject* task_done(PyObject* /*self*/, PyObject* args) Py_XDECREF(repr); Py_XDECREF(str); - qCWarning(dcThingManager()) << "Exception:" << bytes; + qCWarning(dcThingManager()) << "Exception in plugin:" << bytes; + PyErr_Clear(); } Py_RETURN_NONE; @@ -75,7 +77,7 @@ static PyMethodDef nymea_methods[] = { {"write", nymea_write, METH_VARARGS, "write to stdout through qDebug()"}, {"flush", nymea_flush, METH_VARARGS, "flush stdout (no-op)"}, - {"task_done", task_done, METH_VARARGS, "callback to clean up after asyc coroutines"}, + {"task_done", PythonIntegrationPlugin::task_done, METH_VARARGS, "callback to clean up after asyc coroutines"}, {nullptr, nullptr, 0, nullptr} // sentinel }; @@ -181,7 +183,9 @@ PyObject *PythonIntegrationPlugin::pyMyThings(PyObject *self, PyObject */*args*/ PyObject* result = PyTuple_New(plugin->m_things.count()); for (int i = 0; i < plugin->m_things.count(); i++) { Thing *thing = plugin->m_things.keys().at(i); - PyTuple_SET_ITEM(result, i, (PyObject*)plugin->m_things.value(thing)); + PyThing *pyThing = plugin->m_things.value(thing); + Py_INCREF(pyThing); + PyTuple_SET_ITEM(result, i, (PyObject*)pyThing); } plugin->m_mutex.unlock(); return result; @@ -395,6 +399,7 @@ void PythonIntegrationPlugin::setupThing(ThingSetupInfo *info) PyThingSetupInfo *pyInfo = (PyThingSetupInfo*)PyObject_CallObject((PyObject*)&PyThingSetupInfoType, NULL); pyInfo->info = info; pyInfo->pyThing = pyThing; + Py_INCREF(pyThing); m_things.insert(info->thing(), pyThing); @@ -572,7 +577,7 @@ bool PythonIntegrationPlugin::callPluginFunction(const QString &function, PyObje { PyGILState_STATE s = PyGILState_Ensure(); - qCDebug(dcThingManager()) << "Calling python plugin function" << function; + qCDebug(dcThingManager()) << "Calling python plugin function" << function << "on plugin" << s_plugins.key(m_module)->pluginName(); PyObject *pFunc = PyObject_GetAttrString(m_module, function.toUtf8()); if(!pFunc || !PyCallable_Check(pFunc)) { PyErr_Clear(); @@ -643,9 +648,10 @@ bool PythonIntegrationPlugin::callPluginFunction(const QString &function, PyObje void PythonIntegrationPlugin::cleanupPyThing(PyThing *pyThing) { // It could happen that the python thread is currently holding the mutex - // whike waiting on a blocking queued connection on the thing (e.g. PyThing_name). + // on the thing (e.g. PyThing_name). // We'd deadlock if we wait for the mutex forever here. So let's process events // while waiting for it... + qWarning() << "Locking cleanup"; while (!pyThing->mutex->tryLock()) { qApp->processEvents(QEventLoop::EventLoopExec); } diff --git a/libnymea-core/integrations/pythonintegrationplugin.h b/libnymea-core/integrations/pythonintegrationplugin.h index 6d4e906c..2f2b2055 100644 --- a/libnymea-core/integrations/pythonintegrationplugin.h +++ b/libnymea-core/integrations/pythonintegrationplugin.h @@ -41,6 +41,10 @@ public: static PyObject* pyMyThings(PyObject *self, PyObject* args); static PyObject* pyAutoThingsAppeared(PyObject *self, PyObject* args); +public: + // python callbacks + static PyObject* task_done(PyObject* self, PyObject* args); + private: void exportIds(); void exportThingClass(const ThingClass &thingClass); diff --git a/plugins/pymock/integrationpluginpymock.py b/plugins/pymock/integrationpluginpymock.py index cd1495e9..c1872187 100644 --- a/plugins/pymock/integrationpluginpymock.py +++ b/plugins/pymock/integrationpluginpymock.py @@ -21,9 +21,11 @@ def startMonitoringAutoThings(): logger.log("Creating new auto thing") descriptor = nymea.ThingDescriptor(pyMockAutoThingClassId, "Python Mock auto thing") autoThingsAppeared([descriptor]) + logger.log("Done start monitoring auto things") async def setupThing(info): + logger.log("setupThing for", info.thing.name) info.finish(nymea.ThingErrorNoError)