diff --git a/connection.cpp b/connection.cpp index 492281f..9696a49 100644 --- a/connection.cpp +++ b/connection.cpp @@ -18,41 +18,6 @@ DBconn *DBconn::ms_primaryConn = NULL; CONNinfo DBconn::ms_basicConnInfo; static boost::mutex s_poolLock; -class MutexLocker -{ -public: - MutexLocker(boost::mutex *lock): m_lock(lock) - { - if (m_lock) - m_lock->lock(); - } - - ~MutexLocker() - { - if (m_lock) - m_lock->unlock(); - } - - // When the exit(code) is being called, static object is being released - // earlier. Hence - it is a good idea to set the current mutex object to - // NULL to avoid ASSERTION in debug mode (specifically on OSX). - MutexLocker& operator =(boost::mutex *lock) - { - if (m_lock) - m_lock->unlock(); - m_lock = lock; - - if (m_lock) - m_lock->lock(); - - return *this; - } - -private: - boost::mutex *m_lock; - bool is_locked; -}; - DBconn::DBconn(const std::wstring &connectString) : m_inUse(false), m_next(NULL), m_prev(NULL), m_minorVersion(0), m_majorVersion(0) diff --git a/include/misc.h b/include/misc.h index 83e5c80..eca6936 100644 --- a/include/misc.h +++ b/include/misc.h @@ -24,5 +24,40 @@ char* WStringToChar(const std::wstring &wstr); std::string generateRandomString(size_t length); std::wstring getTemporaryDirectoryPath(); +class MutexLocker +{ +public: + MutexLocker(boost::mutex *lock): m_lock(lock) + { + if (m_lock != NULL) + m_lock->lock(); + } + + ~MutexLocker() + { + if (m_lock != NULL) + m_lock->unlock(); + m_lock = NULL; + } + + // When the exit(code) is being called, static object is being released + // earlier. Hence - it is a good idea to set the current mutex object to + // NULL to avoid ASSERTION in debug mode (specifically on OSX). + MutexLocker& operator =(boost::mutex *lock) + { + if (m_lock != NULL) + m_lock->unlock(); + m_lock = lock; + + if (m_lock != NULL) + m_lock->lock(); + + return *this; + } + +private: + boost::mutex *m_lock; +}; + #endif // MISC_H diff --git a/unix.cpp b/unix.cpp index 7098e9b..31fdbfb 100644 --- a/unix.cpp +++ b/unix.cpp @@ -18,6 +18,8 @@ #include #include +static boost::mutex s_loggerLock; + using namespace std; void printVersion(); @@ -45,6 +47,7 @@ void LogMessage(const std::wstring &msg, const int &level) { std::wofstream out; bool writeToStdOut = false; + MutexLocker locker(&s_loggerLock); if (!logFile.empty()) { @@ -100,6 +103,14 @@ void LogMessage(const std::wstring &msg, const int &level) std::wcout << logTimeString; else out.write(logTimeString.c_str(), logTimeString.size()); + // On system exit, boost::mutex object calls + // pthread_mutex_destroy(...) on the underlying native mutex object. + // But - it returns errorcode 'BUSY' instead of 0. Because - it was + // still keeping the lock on the resource. And, that results into + // an assertion in debug mode. + // + // Hence - we need to unlock the mutex before calling system exit. + locker = (boost::mutex *)NULL; exit(1); break; case LOG_STARTUP: