diff --git a/src/cpp/SingletonManager/SessionManager.cpp b/src/cpp/SingletonManager/SessionManager.cpp index 0d6e76a1b..560aab7a8 100644 --- a/src/cpp/SingletonManager/SessionManager.cpp +++ b/src/cpp/SingletonManager/SessionManager.cpp @@ -14,7 +14,7 @@ SessionManager* SessionManager::getInstance() } SessionManager::SessionManager() - : mInitalized(false) + : mInitalized(false), mDeadLockedSessionCount(0) { } @@ -89,6 +89,7 @@ void SessionManager::deinitalize() delete mValidations[i]; } + printf("[SessionManager::deinitalize] count of dead locked sessions: %d\n", mDeadLockedSessionCount); mInitalized = false; mWorkingMutex.unlock(); @@ -277,6 +278,7 @@ bool SessionManager::releaseSession(int requestHandleSession) bool SessionManager::isExist(int requestHandleSession) { + static const char* function_name = "SessionManager::isExist"; if (!mInitalized) { printf("[SessionManager::%s] not initialized any more\n", __FUNCTION__); return false; @@ -294,7 +296,13 @@ bool SessionManager::isExist(int requestHandleSession) auto it = mRequestSessionMap.find(requestHandleSession); if (it != mRequestSessionMap.end()) { result = true; - if (!it->second->isActive()) { + int iResult = it->second->isActive(); + if (-1 == iResult) { + auto em = ErrorManager::getInstance(); + em->addError(new Error(function_name, "session return locked")); + em->sendErrorsAsEmail(); + } + if (0 == iResult) { printf("[SessionManager::isExist] session isn't active\n"); } } @@ -321,6 +329,7 @@ Session* SessionManager::getSession(const Poco::Net::HTTPServerRequest& request) Session* SessionManager::getSession(int handle) { + static const char* function_name = "SessionManager::getSession"; if (!mInitalized) { printf("[SessionManager::%s] not initialized any more\n", __FUNCTION__); return nullptr; @@ -339,7 +348,15 @@ Session* SessionManager::getSession(int handle) auto it = mRequestSessionMap.find(handle); if (it != mRequestSessionMap.end()) { result = it->second; - if (!result->isActive()) { + int iResult = result->isActive(); + if (iResult == -1) { + auto em = ErrorManager::getInstance(); + em->addError(new Error(function_name, "session is locked")); + em->sendErrorsAsEmail(); + mWorkingMutex.unlock(); + return nullptr; + } + if (0 == iResult) { //printf("[SessionManager::getSession] session isn't active\n"); mWorkingMutex.unlock(); return nullptr; @@ -382,6 +399,14 @@ Session* SessionManager::findByUserId(int userId) } //mWorkingMutex.lock(); for (auto it = mRequestSessionMap.begin(); it != mRequestSessionMap.end(); it++) { + while (it->second->isDeadLocked()) + { + it = mRequestSessionMap.erase(it); + mDeadLockedSessionCount++; + auto em = ErrorManager::getInstance(); + em->addError(new ParamError("SessionManager::findByUserId", "new dead locked session found, sum dead lock sessions:", mDeadLockedSessionCount)); + em->sendErrorsAsEmail(); + } auto user = it->second->getNewUser(); auto em = ErrorManager::getInstance(); if(!user) continue; @@ -422,6 +447,10 @@ std::vector SessionManager::findAllByUserId(int userId) } //mWorkingMutex.lock(); for (auto it = mRequestSessionMap.begin(); it != mRequestSessionMap.end(); it++) { + if (it->second->isDeadLocked()) { + it = mRequestSessionMap.erase(it); + mDeadLockedSessionCount++; + } auto user = it->second->getNewUser(); if (userId == user->getModel()->getID()) { //return it->second; @@ -448,6 +477,10 @@ Session* SessionManager::findByEmail(const std::string& email) } //mWorkingMutex.lock(); for (auto it = mRequestSessionMap.begin(); it != mRequestSessionMap.end(); it++) { + if (it->second->isDeadLocked()) { + it = mRequestSessionMap.erase(it); + mDeadLockedSessionCount++; + } auto user = it->second->getNewUser(); if (email == user->getModel()->getEmail()) { return it->second; @@ -477,9 +510,11 @@ void SessionManager::checkTimeoutSession() for (auto it = mRequestSessionMap.begin(); it != mRequestSessionMap.end(); it++) { if (it->second->tryLock()) { - it->second->unlock(); // skip already disabled sessions - if (!it->second->isActive()) continue; + if (!it->second->isActive()) { + it->second->unlock(); + continue; + } } else { // skip dead locked sessions @@ -487,6 +522,7 @@ void SessionManager::checkTimeoutSession() } Poco::Timespan timeElapsed(now - it->second->getLastActivity()); + it->second->unlock(); if (timeElapsed > timeout) { toRemove.push(it->first); } @@ -513,7 +549,11 @@ void SessionManager::deleteLoginCookies(Poco::Net::HTTPServerRequest& request, P if (activeSession) { try { int session_id = atoi(it->second.data()); - if (session_id == activeSession->getHandle()) continue; + if (activeSession->tryLock()) { + bool session_id_is_handle = session_id == activeSession->getHandle(); + activeSession->unlock(); + if (session_id_is_handle) continue; + } } catch (...) {} } diff --git a/src/cpp/SingletonManager/SessionManager.h b/src/cpp/SingletonManager/SessionManager.h index 208de09be..2f720b82b 100644 --- a/src/cpp/SingletonManager/SessionManager.h +++ b/src/cpp/SingletonManager/SessionManager.h @@ -84,6 +84,7 @@ protected: // sessions storage std::map mRequestSessionMap; std::stack mEmptyRequestStack; + int mDeadLockedSessionCount; bool mInitalized; diff --git a/src/cpp/model/Session.cpp b/src/cpp/model/Session.cpp index 5139ddede..568d4c6e6 100644 --- a/src/cpp/model/Session.cpp +++ b/src/cpp/model/Session.cpp @@ -131,6 +131,47 @@ void Session::reset() //printf("[Session::reset] finished\n"); } +int Session::isActive() +{ + int ret = 0; + try { + mWorkMutex.tryLock(100); + } + catch (Poco::TimeoutException &ex) { + return -1; + } + ret = (int)mActive; + unlock(); + return ret; + +} + +bool Session::isDeadLocked() +{ + try { + mWorkMutex.tryLock(200); + unlock(); + return false; + } + catch (Poco::Exception& ex) { + + } + return true; +} + +bool Session::setActive(bool active) +{ + try { + mWorkMutex.tryLock(100); + } + catch (Poco::TimeoutException &ex) { + return false; + } + mActive = active; + unlock(); + return true; +} + void Session::updateTimeout() { lock("Session::updateTimeout"); diff --git a/src/cpp/model/Session.h b/src/cpp/model/Session.h index 69a9612e0..dcb321242 100644 --- a/src/cpp/model/Session.h +++ b/src/cpp/model/Session.h @@ -162,8 +162,14 @@ public: return mEmailVerificationCodeObject->getModel()->getType(); } - inline bool isActive() { bool bret = false; lock("Session::isActive"); bret = mActive; unlock(); return bret; } - inline void setActive(bool active) { lock("Sessions::setActive"); mActive = active; unlock(); } + //! \return -1 if session is locked + //! \return 1 if session is active + //! \return 0 + int isActive(); + //! \return false if session is locked + bool setActive(bool active); + + bool isDeadLocked(); inline Poco::DateTime getLastActivity() { return mLastActivity; }