Added more mutexes in eventmanager, fixed exiting destruction bug

checksum-failure-logging
EricLiu2000 2019-08-07 13:12:16 -04:00
parent 9629864f1b
commit ef16e60025
5 changed files with 43 additions and 17 deletions

View File

@ -3,20 +3,32 @@
using namespace icsneo; using namespace icsneo;
static std::unique_ptr<EventManager> singleton;
EventManager& EventManager::GetInstance() { EventManager& EventManager::GetInstance() {
if(!singleton) static EventManager inst;
singleton = std::unique_ptr<EventManager>(new EventManager()); return inst;
return *singleton.get();
} }
void EventManager::ResetInstance() { void EventManager::ResetInstance() {
singleton = std::unique_ptr<EventManager>(new EventManager()); std::lock_guard<std::mutex> eventsLock(eventsMutex);
std::lock_guard<std::mutex> errorsLock(errorsMutex);
std::lock_guard<std::mutex> downgradedThreadsLock(downgradedThreadsMutex);
std::lock_guard<std::mutex> callbacksLock(callbacksMutex);
std::lock_guard<std::mutex> callbackIDLock(callbackIDMutex);
std::lock_guard<std::mutex> eventLimitLock(eventLimitMutex);
events.clear();
lastUserErrors.clear();
downgradedThreads.clear();
callbacks.clear();
callbackID = 0;
eventLimit = 10000;
} }
int EventManager::addEventCallback(const EventCallback &cb) { int EventManager::addEventCallback(const EventCallback &cb) {
std::lock_guard<std::mutex> lk(callbacksMutex); std::lock_guard<std::mutex> callbacksLock(callbacksMutex);
std::lock_guard<std::mutex> callbackIDLock(callbackIDMutex);
callbacks.insert({callbackID, cb}); callbacks.insert({callbackID, cb});
return callbackID++; return callbackID++;
} }

View File

@ -1,5 +1,6 @@
#include "icsneo/device/device.h" #include "icsneo/device/device.h"
#include "icsneo/communication/message/callback/messagecallback.h" #include "icsneo/communication/message/callback/messagecallback.h"
#include "icsneo/api/eventmanager.h"
#include "icsneo/communication/command.h" #include "icsneo/communication/command.h"
#include <string.h> #include <string.h>
#include <iostream> #include <iostream>

View File

@ -17,13 +17,19 @@ typedef std::function<void (APIEvent::Type, APIEvent::Severity)> device_eventhan
class EventManager { class EventManager {
public: public:
~EventManager() {
destructing = true;
}
static EventManager& GetInstance(); static EventManager& GetInstance();
static void ResetInstance(); void ResetInstance();
// If this thread is not in the map, add it to be ignored // If this thread is not in the map, add it to be ignored
// If it is, set it to be ignored // If it is, set it to be ignored
void downgradeErrorsOnCurrentThread() { void downgradeErrorsOnCurrentThread() {
if(destructing)
return;
std::lock_guard<std::mutex> lk(downgradedThreadsMutex); std::lock_guard<std::mutex> lk(downgradedThreadsMutex);
auto i = downgradedThreads.find(std::this_thread::get_id()); auto i = downgradedThreads.find(std::this_thread::get_id());
if(i != downgradedThreads.end()) { if(i != downgradedThreads.end()) {
@ -35,6 +41,8 @@ public:
// If this thread exists in the map, turn off downgrading // If this thread exists in the map, turn off downgrading
void cancelErrorDowngradingOnCurrentThread() { void cancelErrorDowngradingOnCurrentThread() {
if(destructing)
return;
std::lock_guard<std::mutex> lk(downgradedThreadsMutex); std::lock_guard<std::mutex> lk(downgradedThreadsMutex);
auto i = downgradedThreads.find(std::this_thread::get_id()); auto i = downgradedThreads.find(std::this_thread::get_id());
if(i != downgradedThreads.end()) { if(i != downgradedThreads.end()) {
@ -63,6 +71,8 @@ public:
APIEvent getLastError(); APIEvent getLastError();
void add(APIEvent event) { void add(APIEvent event) {
if(destructing)
return;
if(event.getSeverity() == APIEvent::Severity::Error) { if(event.getSeverity() == APIEvent::Severity::Error) {
// if the error was added on a thread that downgrades errors (non-user thread) // if the error was added on a thread that downgrades errors (non-user thread)
std::lock_guard<std::mutex> lk(downgradedThreadsMutex); std::lock_guard<std::mutex> lk(downgradedThreadsMutex);
@ -93,7 +103,7 @@ public:
void discard(EventFilter filter = EventFilter()); void discard(EventFilter filter = EventFilter());
void setEventLimit(size_t newLimit) { void setEventLimit(size_t newLimit) {
std::lock_guard<std::mutex> lk(eventsMutex); std::lock_guard<std::mutex> eventLimitLock(eventLimitMutex);
if(newLimit == eventLimit) if(newLimit == eventLimit)
return; return;
@ -104,17 +114,19 @@ public:
} }
eventLimit = newLimit; eventLimit = newLimit;
std::lock_guard<std::mutex> eventsLock(eventsMutex);
if(enforceLimit()) if(enforceLimit())
add_internal_event(APIEvent(APIEvent::Type::TooManyEvents, APIEvent::Severity::EventWarning)); add_internal_event(APIEvent(APIEvent::Type::TooManyEvents, APIEvent::Severity::EventWarning));
} }
size_t getEventLimit() const { size_t getEventLimit() const {
std::lock_guard<std::mutex> lk(eventsMutex); std::lock_guard<std::mutex> lk(eventLimitMutex);
return eventLimit; return eventLimit;
} }
private: private:
EventManager() : eventsMutex(), errorsMutex(), downgradedThreadsMutex(), callbacksMutex(), downgradedThreads(), callbacks(), events(), lastUserErrors(), eventLimit(10000) {} EventManager() : eventsMutex(), errorsMutex(), downgradedThreadsMutex(), callbacksMutex(), callbackIDMutex(), eventLimitMutex(), downgradedThreads(), callbacks(), events(), lastUserErrors(), eventLimit(10000) {}
EventManager(const EventManager &other); EventManager(const EventManager &other);
EventManager& operator=(const EventManager &other); EventManager& operator=(const EventManager &other);
@ -124,12 +136,17 @@ private:
mutable std::mutex downgradedThreadsMutex; mutable std::mutex downgradedThreadsMutex;
mutable std::mutex callbacksMutex; mutable std::mutex callbacksMutex;
mutable std::mutex callbackIDMutex;
mutable std::mutex eventLimitMutex;
std::map<std::thread::id, bool> downgradedThreads; std::map<std::thread::id, bool> downgradedThreads;
std::map<int, EventCallback> callbacks; std::map<int, EventCallback> callbacks;
int callbackID = 0; int callbackID = 0;
bool destructing = false;
// Stores all events // Stores all events
std::list<APIEvent> events; std::list<APIEvent> events;
std::map<std::thread::id, APIEvent> lastUserErrors; std::map<std::thread::id, APIEvent> lastUserErrors;

View File

@ -22,7 +22,6 @@ namespace icsneo {
class Device { class Device {
public: public:
virtual ~Device() { virtual ~Device() {
destructing = true;
if(isMessagePollingEnabled()) if(isMessagePollingEnabled())
disableMessagePolling(); disableMessagePolling();
close(); close();
@ -121,8 +120,7 @@ protected:
virtual device_eventhandler_t makeEventHandler() { virtual device_eventhandler_t makeEventHandler() {
return [this](APIEvent::Type type, APIEvent::Severity severity) { return [this](APIEvent::Type type, APIEvent::Severity severity) {
if(!destructing) EventManager::GetInstance().add(type, severity, this);
EventManager::GetInstance().add(type, severity, this);
}; };
} }
@ -178,8 +176,6 @@ private:
size_t pollingMessageLimit = 20000; size_t pollingMessageLimit = 20000;
moodycamel::BlockingConcurrentQueue<std::shared_ptr<Message>> pollingContainer; moodycamel::BlockingConcurrentQueue<std::shared_ptr<Message>> pollingContainer;
void enforcePollingMessageLimit(); void enforcePollingMessageLimit();
bool destructing = false;
}; };
} }

View File

@ -11,7 +11,7 @@ class EventManagerTest : public ::testing::Test {
protected: protected:
// Start with a clean instance of eventmanager for every test // Start with a clean instance of eventmanager for every test
void SetUp() override { void SetUp() override {
EventManager::ResetInstance(); EventManager::GetInstance().ResetInstance();
} }
}; };