From 70fbc25dbd3b2ef454ebf9430b9cdb310e7e6b61 Mon Sep 17 00:00:00 2001 From: Peter Keresztes Schmidt Date: Mon, 8 Feb 2021 18:59:25 +0100 Subject: [PATCH 1/2] Mutex: Change method signatures so they resemble std::unique_lock a bit more try_lock_for should specify in their return value whether obtaining the lock succeeded. --- src/zm_thread.cpp | 12 +++++------- src/zm_thread.h | 6 +++--- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src/zm_thread.cpp b/src/zm_thread.cpp index ad5670fec..f6c6cdb7f 100644 --- a/src/zm_thread.cpp +++ b/src/zm_thread.cpp @@ -59,7 +59,7 @@ Mutex::~Mutex() { Error("Unable to destroy pthread mutex: %s", strerror(errno)); } -int Mutex::trylock() { +int Mutex::try_lock() { return pthread_mutex_trylock(&mMutex); } void Mutex::lock() { @@ -68,16 +68,14 @@ void Mutex::lock() { //Debug(3, "Lock"); } -void Mutex::lock( int secs ) { +bool Mutex::try_lock_for(int secs) { struct timespec timeout = getTimeout(secs); - if ( pthread_mutex_timedlock(&mMutex, &timeout) < 0 ) - throw ThreadException(stringtf("Unable to timedlock pthread mutex: %s", strerror(errno))); + return pthread_mutex_timedlock(&mMutex, &timeout) == 0; } -void Mutex::lock( double secs ) { +bool Mutex::try_lock_for(double secs) { struct timespec timeout = getTimeout(secs); - if ( pthread_mutex_timedlock(&mMutex, &timeout) < 0 ) - throw ThreadException(stringtf("Unable to timedlock pthread mutex: %s", strerror(errno))); + return pthread_mutex_timedlock(&mMutex, &timeout) == 0; } void Mutex::unlock() { diff --git a/src/zm_thread.h b/src/zm_thread.h index 3a6e34797..4cdadb370 100644 --- a/src/zm_thread.h +++ b/src/zm_thread.h @@ -78,10 +78,10 @@ class Mutex { } public: - int trylock(); + int try_lock(); void lock(); - void lock( int secs ); - void lock( double secs ); + bool try_lock_for(int secs); + bool try_lock_for(double secs); void unlock(); bool locked(); }; From 7e7b1a0b1f6cbad611a1e15104edcf37539256cd Mon Sep 17 00:00:00 2001 From: Peter Keresztes Schmidt Date: Mon, 8 Feb 2021 19:04:40 +0100 Subject: [PATCH 2/2] Logger: Try harder to obtain the DB lock Since we are now multi-threaded it can happen quite easily that a log message should be written to the DB on one thread while the other thread executes another query. Don't bail out immediately in the logging code, instead try to obtain the lock within 1s. --- src/zm_logger.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/zm_logger.cpp b/src/zm_logger.cpp index 61cea253b..d10840848 100644 --- a/src/zm_logger.cpp +++ b/src/zm_logger.cpp @@ -534,7 +534,7 @@ void Logger::logPrint(bool hex, const char * const filepath, const int line, con } // end if level <= mFileLevel if ( level <= mDatabaseLevel ) { - if ( !db_mutex.trylock() ) { + if (db_mutex.try_lock_for(1)) { char escapedString[(strlen(syslogStart)*2)+1]; mysql_real_escape_string(&dbconn, escapedString, syslogStart, strlen(syslogStart)); @@ -556,7 +556,7 @@ void Logger::logPrint(bool hex, const char * const filepath, const int line, con } else { Level tempDatabaseLevel = mDatabaseLevel; databaseLevel(NOLOG); - Error("Can't insert log entry: sql(%s) error(%s)", syslogStart, mysql_error(&dbconn)); + Error("Can't insert log entry since the DB lock could not be obtained. Message: %s", syslogStart); databaseLevel(tempDatabaseLevel); } } // end if level <= mDatabaseLevel