Fix some data races (#890)

This commit is contained in:
Murat Seker 2020-07-22 16:43:24 +02:00 committed by GitHub
parent 6362cfcc1b
commit 126c18e003
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 69 additions and 50 deletions

View File

@ -18,6 +18,8 @@
#include <utils/Components.h> #include <utils/Components.h>
#include <utils/Image.h> #include <utils/Image.h>
#include <atomic>
class Hyperion; class Hyperion;
class Logger; class Logger;
@ -88,7 +90,7 @@ private:
Logger *_log; Logger *_log;
// Reflects whenever this effects should interupt (timeout or external request) // Reflects whenever this effects should interupt (timeout or external request)
bool _interupt = false; std::atomic<bool> _interupt {};
QSize _imageSize; QSize _imageSize;
QImage _image; QImage _image;

View File

@ -79,11 +79,6 @@ public:
/// ///
const quint8 & getInstanceIndex() { return _instIndex; } const quint8 & getInstanceIndex() { return _instIndex; }
///
/// Returns the number of attached leds
///
unsigned getLedCount() const;
/// ///
/// @brief Return the size of led grid /// @brief Return the size of led grid
/// ///
@ -92,8 +87,6 @@ public:
/// gets the methode how image is maped to leds /// gets the methode how image is maped to leds
const int & getLedMappingType(); const int & getLedMappingType();
int getLatchTime() const;
/// forward smoothing config /// forward smoothing config
unsigned addSmoothingConfig(int settlingTime_ms, double ledUpdateFrequency_hz=25.0, unsigned updateDelay=0); unsigned addSmoothingConfig(int settlingTime_ms, double ledUpdateFrequency_hz=25.0, unsigned updateDelay=0);
unsigned updateSmoothingConfig(unsigned id, int settlingTime_ms=200, double ledUpdateFrequency_hz=25.0, unsigned updateDelay=0); unsigned updateSmoothingConfig(unsigned id, int settlingTime_ms=200, double ledUpdateFrequency_hz=25.0, unsigned updateDelay=0);
@ -113,6 +106,12 @@ public:
LedDevice * getActiveDevice() const; LedDevice * getActiveDevice() const;
public slots: public slots:
int getLatchTime() const;
///
/// Returns the number of attached leds
///
unsigned getLedCount() const;
/// ///
/// @brief Register a new input by priority, the priority is not active (timeout -100 isn't muxer recognized) until you start to update the data with setInput() /// @brief Register a new input by priority, the priority is not active (timeout -100 isn't muxer recognized) until you start to update the data with setInput()

View File

@ -39,16 +39,6 @@ public:
void start(); void start();
void stop(); void stop();
quint16 getPort() const { return _port; }
/// check if server has been inited
bool isInited() const { return _inited; }
///
/// @brief Set a new description, if empty the description is NotFound for clients
///
void setSSDPDescription(const QString & desc);
signals: signals:
/// ///
/// @emits whenever server is started or stopped (to sync with SSDPHandler) /// @emits whenever server is started or stopped (to sync with SSDPHandler)
@ -78,6 +68,16 @@ public slots:
/// ///
void handleSettingsUpdate(const settings::type& type, const QJsonDocument& config); void handleSettingsUpdate(const settings::type& type, const QJsonDocument& config);
///
/// @brief Set a new description, if empty the description is NotFound for clients
///
void setSSDPDescription(const QString & desc);
/// check if server has been inited
bool isInited() const { return _inited; }
quint16 getPort() const { return _port; }
private: private:
QJsonDocument _config; QJsonDocument _config;
bool _useSsl; bool _useSsl;

View File

@ -53,6 +53,9 @@ Effect::Effect(Hyperion *hyperion, int priority, int timeout, const QString &scr
Effect::~Effect() Effect::~Effect()
{ {
requestInterruption();
wait();
delete _painter; delete _painter;
_imageStack.clear(); _imageStack.clear();
} }
@ -82,10 +85,14 @@ void Effect::run()
PyModule_AddObject(module, "__effectObj", PyCapsule_New((void*)this, "hyperion.__effectObj", nullptr)); PyModule_AddObject(module, "__effectObj", PyCapsule_New((void*)this, "hyperion.__effectObj", nullptr));
// add ledCount variable to the interpreter // add ledCount variable to the interpreter
PyObject_SetAttrString(module, "ledCount", Py_BuildValue("i", _hyperion->getLedCount())); unsigned ledCount = 0;
QMetaObject::invokeMethod(_hyperion, "getLedCount", Qt::BlockingQueuedConnection, Q_RETURN_ARG(unsigned, ledCount));
PyObject_SetAttrString(module, "ledCount", Py_BuildValue("i", ledCount));
// add minimumWriteTime variable to the interpreter // add minimumWriteTime variable to the interpreter
PyObject_SetAttrString(module, "latchTime", Py_BuildValue("i", _hyperion->getLatchTime())); int latchTime = 0;
QMetaObject::invokeMethod(_hyperion, "getLatchTime", Qt::BlockingQueuedConnection, Q_RETURN_ARG(int, latchTime));
PyObject_SetAttrString(module, "latchTime", Py_BuildValue("i", latchTime));
// add a args variable to the interpreter // add a args variable to the interpreter
PyObject_SetAttrString(module, "args", EffectModule::json2python(_args)); PyObject_SetAttrString(module, "args", EffectModule::json2python(_args));

View File

@ -144,7 +144,7 @@ PyObject* EffectModule::wrapSetColor(PyObject *self, PyObject *args)
{ {
getEffect()->_colors.fill(color); getEffect()->_colors.fill(color);
QVector<ColorRgb> _cQV = getEffect()->_colors; QVector<ColorRgb> _cQV = getEffect()->_colors;
getEffect()->setInput(getEffect()->_priority, std::vector<ColorRgb>( _cQV.begin(), _cQV.end() ), timeout, false); emit getEffect()->setInput(getEffect()->_priority, std::vector<ColorRgb>( _cQV.begin(), _cQV.end() ), timeout, false);
Py_RETURN_NONE; Py_RETURN_NONE;
} }
return nullptr; return nullptr;
@ -163,7 +163,7 @@ PyObject* EffectModule::wrapSetColor(PyObject *self, PyObject *args)
char * data = PyByteArray_AS_STRING(bytearray); char * data = PyByteArray_AS_STRING(bytearray);
memcpy(getEffect()->_colors.data(), data, length); memcpy(getEffect()->_colors.data(), data, length);
QVector<ColorRgb> _cQV = getEffect()->_colors; QVector<ColorRgb> _cQV = getEffect()->_colors;
getEffect()->setInput(getEffect()->_priority, std::vector<ColorRgb>( _cQV.begin(), _cQV.end() ), timeout, false); emit getEffect()->setInput(getEffect()->_priority, std::vector<ColorRgb>( _cQV.begin(), _cQV.end() ), timeout, false);
Py_RETURN_NONE; Py_RETURN_NONE;
} }
else else
@ -218,7 +218,7 @@ PyObject* EffectModule::wrapSetImage(PyObject *self, PyObject *args)
Image<ColorRgb> image(width, height); Image<ColorRgb> image(width, height);
char * data = PyByteArray_AS_STRING(bytearray); char * data = PyByteArray_AS_STRING(bytearray);
memcpy(image.memptr(), data, length); memcpy(image.memptr(), data, length);
getEffect()->setInputImage(getEffect()->_priority, image, timeout, false); emit getEffect()->setInputImage(getEffect()->_priority, image, timeout, false);
Py_RETURN_NONE; Py_RETURN_NONE;
} }
else else
@ -375,7 +375,7 @@ PyObject* EffectModule::wrapImageShow(PyObject *self, PyObject *args)
} }
memcpy(image.memptr(), binaryImage.data(), binaryImage.size()); memcpy(image.memptr(), binaryImage.data(), binaryImage.size());
getEffect()->setInputImage(getEffect()->_priority, image, timeout, false); emit getEffect()->setInputImage(getEffect()->_priority, image, timeout, false);
return Py_BuildValue(""); return Py_BuildValue("");
} }

View File

@ -54,7 +54,10 @@ void SSDPHandler::initServer()
} }
// startup if localAddress is found // startup if localAddress is found
if(!_localAddress.isEmpty() && _webserver->isInited()) bool isInited = false;
QMetaObject::invokeMethod(_webserver, "isInited", Qt::BlockingQueuedConnection, Q_RETURN_ARG(bool, isInited));
if(!_localAddress.isEmpty() && isInited)
{ {
handleWebServerStateChange(true); handleWebServerStateChange(true);
} }
@ -100,14 +103,14 @@ void SSDPHandler::handleWebServerStateChange(const bool newState)
if(newState) if(newState)
{ {
// refresh info // refresh info
_webserver->setSSDPDescription(buildDesc()); QMetaObject::invokeMethod(_webserver, "setSSDPDescription", Qt::BlockingQueuedConnection, Q_ARG(QString, buildDesc()));
setDescriptionAddress(getDescAddress()); setDescriptionAddress(getDescAddress());
if(start()) if(start())
sendAnnounceList(true); sendAnnounceList(true);
} }
else else
{ {
_webserver->setSSDPDescription(""); QMetaObject::invokeMethod(_webserver, "setSSDPDescription", Qt::BlockingQueuedConnection, Q_ARG(QString, ""));
sendAnnounceList(false); sendAnnounceList(false);
stop(); stop();
} }
@ -124,7 +127,7 @@ void SSDPHandler::handleNetworkConfigurationChanged(const QNetworkConfiguration
// update desc & notify new ip // update desc & notify new ip
_localAddress = localAddress; _localAddress = localAddress;
_webserver->setSSDPDescription(buildDesc()); QMetaObject::invokeMethod(_webserver, "setSSDPDescription", Qt::BlockingQueuedConnection, Q_ARG(QString, buildDesc()));
setDescriptionAddress(getDescAddress()); setDescriptionAddress(getDescAddress());
sendAnnounceList(true); sendAnnounceList(true);
} }
@ -177,7 +180,9 @@ QString SSDPHandler::getDescAddress() const
QString SSDPHandler::getBaseAddress() const QString SSDPHandler::getBaseAddress() const
{ {
return QString("http://%1:%2/").arg(_localAddress).arg(_webserver->getPort()); quint16 port = 0;
QMetaObject::invokeMethod(_webserver, "getPort", Qt::BlockingQueuedConnection, Q_RETURN_ARG(quint16, port));
return QString("http://%1:%2/").arg(_localAddress).arg(port);
} }
QString SSDPHandler::buildDesc() const QString SSDPHandler::buildDesc() const
@ -195,3 +200,4 @@ void SSDPHandler::sendAnnounceList(const bool alive)
alive ? SSDPServer::sendAlive(entry) : SSDPServer::sendByeBye(entry); alive ? SSDPServer::sendAlive(entry) : SSDPServer::sendByeBye(entry);
} }
} }

View File

@ -12,7 +12,6 @@
// netUtil // netUtil
#include <utils/NetUtils.h> #include <utils/NetUtils.h>
WebServer::WebServer(const QJsonDocument& config, const bool& useSsl, QObject * parent) WebServer::WebServer(const QJsonDocument& config, const bool& useSsl, QObject * parent)
: QObject(parent) : QObject(parent)
, _config(config) , _config(config)

View File

@ -175,31 +175,32 @@ void HyperionDaemon::freeObjects()
// destroy network first as a client might want to access hyperion // destroy network first as a client might want to access hyperion
delete _jsonServer; delete _jsonServer;
_flatBufferServer->thread()->quit();
_flatBufferServer->thread()->wait(1000);
delete _flatBufferServer->thread();
delete _flatBufferServer;
_protoServer->thread()->quit(); auto flatBufferServerThread = _flatBufferServer->thread();
_protoServer->thread()->wait(1000); flatBufferServerThread->quit();
delete _protoServer->thread(); flatBufferServerThread->wait();
delete _protoServer; delete flatBufferServerThread;
auto protoServerThread = _protoServer->thread();
protoServerThread->quit();
protoServerThread->wait();
delete protoServerThread;
//ssdp before webserver //ssdp before webserver
_ssdp->thread()->quit(); auto ssdpThread = _ssdp->thread();
_ssdp->thread()->wait(1000); ssdpThread->quit();
delete _ssdp->thread(); ssdpThread->wait();
delete _ssdp; delete ssdpThread;
_webserver->thread()->quit(); auto webserverThread =_webserver->thread();
_webserver->thread()->wait(1000); webserverThread->quit();
delete _webserver->thread(); webserverThread->wait();
delete _webserver; delete webserverThread;
_sslWebserver->thread()->quit(); auto sslWebserverThread =_sslWebserver->thread();
_sslWebserver->thread()->wait(1000); sslWebserverThread->quit();
delete _sslWebserver->thread(); sslWebserverThread->wait();
delete _sslWebserver; delete sslWebserverThread;
#ifdef ENABLE_CEC #ifdef ENABLE_CEC
_cecHandler->thread()->quit(); _cecHandler->thread()->quit();
@ -247,6 +248,7 @@ void HyperionDaemon::startNetworkServices()
fbThread->setObjectName("FlatBufferServerThread"); fbThread->setObjectName("FlatBufferServerThread");
_flatBufferServer->moveToThread(fbThread); _flatBufferServer->moveToThread(fbThread);
connect(fbThread, &QThread::started, _flatBufferServer, &FlatBufferServer::initServer); connect(fbThread, &QThread::started, _flatBufferServer, &FlatBufferServer::initServer);
connect(fbThread, &QThread::finished, _flatBufferServer, &FlatBufferServer::deleteLater);
connect(this, &HyperionDaemon::settingsChanged, _flatBufferServer, &FlatBufferServer::handleSettingsUpdate); connect(this, &HyperionDaemon::settingsChanged, _flatBufferServer, &FlatBufferServer::handleSettingsUpdate);
fbThread->start(); fbThread->start();
@ -256,6 +258,7 @@ void HyperionDaemon::startNetworkServices()
pThread->setObjectName("ProtoServerThread"); pThread->setObjectName("ProtoServerThread");
_protoServer->moveToThread(pThread); _protoServer->moveToThread(pThread);
connect(pThread, &QThread::started, _protoServer, &ProtoServer::initServer); connect(pThread, &QThread::started, _protoServer, &ProtoServer::initServer);
connect(pThread, &QThread::finished, _protoServer, &ProtoServer::deleteLater);
connect(this, &HyperionDaemon::settingsChanged, _protoServer, &ProtoServer::handleSettingsUpdate); connect(this, &HyperionDaemon::settingsChanged, _protoServer, &ProtoServer::handleSettingsUpdate);
pThread->start(); pThread->start();
@ -265,6 +268,7 @@ void HyperionDaemon::startNetworkServices()
wsThread->setObjectName("WebServerThread"); wsThread->setObjectName("WebServerThread");
_webserver->moveToThread(wsThread); _webserver->moveToThread(wsThread);
connect(wsThread, &QThread::started, _webserver, &WebServer::initServer); connect(wsThread, &QThread::started, _webserver, &WebServer::initServer);
connect(wsThread, &QThread::finished, _webserver, &WebServer::deleteLater);
connect(this, &HyperionDaemon::settingsChanged, _webserver, &WebServer::handleSettingsUpdate); connect(this, &HyperionDaemon::settingsChanged, _webserver, &WebServer::handleSettingsUpdate);
wsThread->start(); wsThread->start();
@ -274,6 +278,7 @@ void HyperionDaemon::startNetworkServices()
sslWsThread->setObjectName("SSLWebServerThread"); sslWsThread->setObjectName("SSLWebServerThread");
_sslWebserver->moveToThread(sslWsThread); _sslWebserver->moveToThread(sslWsThread);
connect(sslWsThread, &QThread::started, _sslWebserver, &WebServer::initServer); connect(sslWsThread, &QThread::started, _sslWebserver, &WebServer::initServer);
connect(sslWsThread, &QThread::finished, _sslWebserver, &WebServer::deleteLater);
connect(this, &HyperionDaemon::settingsChanged, _sslWebserver, &WebServer::handleSettingsUpdate); connect(this, &HyperionDaemon::settingsChanged, _sslWebserver, &WebServer::handleSettingsUpdate);
sslWsThread->start(); sslWsThread->start();
@ -283,6 +288,7 @@ void HyperionDaemon::startNetworkServices()
ssdpThread->setObjectName("SSDPThread"); ssdpThread->setObjectName("SSDPThread");
_ssdp->moveToThread(ssdpThread); _ssdp->moveToThread(ssdpThread);
connect(ssdpThread, &QThread::started, _ssdp, &SSDPHandler::initServer); connect(ssdpThread, &QThread::started, _ssdp, &SSDPHandler::initServer);
connect(ssdpThread, &QThread::finished, _ssdp, &SSDPHandler::deleteLater);
connect(_webserver, &WebServer::stateChange, _ssdp, &SSDPHandler::handleWebServerStateChange); connect(_webserver, &WebServer::stateChange, _ssdp, &SSDPHandler::handleWebServerStateChange);
connect(this, &HyperionDaemon::settingsChanged, _ssdp, &SSDPHandler::handleSettingsUpdate); connect(this, &HyperionDaemon::settingsChanged, _ssdp, &SSDPHandler::handleSettingsUpdate);
ssdpThread->start(); ssdpThread->start();