From a96fb7b7f0c9c73357aa2f38e0e985f4eb0161d7 Mon Sep 17 00:00:00 2001 From: Christian Schuett Date: Fri, 14 Feb 2014 18:40:22 +0100 Subject: [PATCH] timerd: prevent events from being deleted while sending them to neutrino in neutrino's timer list sometimes appears an entry with random values after deleting one because thread safety is not guaranteed for timerd's event list while sending items to neutrino, so let's lock the mutex earlier and unlock it later Signed-off-by: Christian Schuett Signed-off-by: Thilo Graf --- src/timerd/timerd.cpp | 6 ++++++ src/timerd/timermanager.cpp | 15 +++++++++++++-- src/timerd/timermanager.h | 2 ++ 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/timerd/timerd.cpp b/src/timerd/timerd.cpp index 4d4538cfe..5f79230a0 100644 --- a/src/timerd/timerd.cpp +++ b/src/timerd/timerd.cpp @@ -59,6 +59,7 @@ bool timerd_parse_command(CBasicMessage::Header &rmsg, int connfd) case CTimerdMsg::CMD_GETSLEEPTIMER: rspGetSleeptimer.eventID = 0; + CTimerManager::getInstance()->lockEvents(); if (CTimerManager::getInstance()->listEvents(events)) { for (pos = events.begin(); pos != events.end(); ++pos) @@ -71,6 +72,7 @@ bool timerd_parse_command(CBasicMessage::Header &rmsg, int connfd) } } } + CTimerManager::getInstance()->unlockEvents(); CBasicServer::send_data(connfd, &rspGetSleeptimer, sizeof(rspGetSleeptimer)); break; @@ -78,6 +80,7 @@ bool timerd_parse_command(CBasicMessage::Header &rmsg, int connfd) CTimerdMsg::commandGetTimer msgGetTimer; CTimerd::responseGetTimer resp; CBasicServer::receive_data(connfd,&msgGetTimer, sizeof(msgGetTimer)); + CTimerManager::getInstance()->lockEvents(); if(CTimerManager::getInstance()->listEvents(events)) { if(events[msgGetTimer.eventID]) @@ -134,11 +137,13 @@ bool timerd_parse_command(CBasicMessage::Header &rmsg, int connfd) } } } + CTimerManager::getInstance()->unlockEvents(); CBasicServer::send_data(connfd, &resp, sizeof(CTimerd::responseGetTimer)); break; case CTimerdMsg::CMD_GETTIMERLIST: CTimerdMsg::generalInteger responseInteger; + CTimerManager::getInstance()->lockEvents(); responseInteger.number = (CTimerManager::getInstance()->listEvents(events)) ? events.size() : 0; if (CBasicServer::send_data(connfd, &responseInteger, sizeof(responseInteger)) == true) @@ -200,6 +205,7 @@ bool timerd_parse_command(CBasicMessage::Header &rmsg, int connfd) CBasicServer::send_data(connfd, &lresp, sizeof(CTimerd::responseGetTimer)); } } + CTimerManager::getInstance()->unlockEvents(); break; case CTimerdMsg::CMD_RESCHEDULETIMER: // event nach vorne oder hinten schieben diff --git a/src/timerd/timermanager.cpp b/src/timerd/timermanager.cpp index ad6262ead..01aae3af6 100644 --- a/src/timerd/timermanager.cpp +++ b/src/timerd/timermanager.cpp @@ -277,12 +277,24 @@ bool CTimerManager::stopEvent(int peventID) } //------------------------------------------------------------ +int CTimerManager::lockEvents() +{ + return pthread_mutex_lock(&tm_eventsMutex); +} + +//------------------------------------------------------------ +int CTimerManager::unlockEvents() +{ + return pthread_mutex_unlock(&tm_eventsMutex); +} + +//------------------------------------------------------------ + bool CTimerManager::listEvents(CTimerEventMap &Events) { if(!&Events) return false; - pthread_mutex_lock(&tm_eventsMutex); Events.clear(); for (CTimerEventMap::iterator pos = events.begin(); pos != events.end(); ++pos) @@ -290,7 +302,6 @@ bool CTimerManager::listEvents(CTimerEventMap &Events) pos->second->Refresh(); Events[pos->second->eventID] = pos->second; } - pthread_mutex_unlock(&tm_eventsMutex); return true; } //------------------------------------------------------------ diff --git a/src/timerd/timermanager.h b/src/timerd/timermanager.h index 708171d3e..7d9a18b22 100644 --- a/src/timerd/timermanager.h +++ b/src/timerd/timermanager.h @@ -237,6 +237,8 @@ public: bool removeEvent(int eventID); bool stopEvent(int eventID); CTimerEvent* getNextEvent(); + int lockEvents(); + int unlockEvents(); bool listEvents(CTimerEventMap &Events); CTimerd::CTimerEventTypes *getEventType(int eventID); // int modifyEvent(int eventID, time_t announceTime, time_t alarmTime, time_t stopTime, uint32_t repeatcount, CTimerd::CTimerEventRepeat evrepeat = CTimerd::TIMERREPEAT_ONCE);