diff options
author | Anthony Towns <aj@erisian.com.au> | 2020-02-11 16:50:22 +1000 |
---|---|---|
committer | Anthony Towns <aj@erisian.com.au> | 2020-05-27 01:31:51 +1000 |
commit | 5478d6c099e76fe070703cc5383cba7b91468b0f (patch) | |
tree | ec02170ef4e628dad3bbec5d7c1199671c5c4c23 /src | |
parent | e685ca19928eec4e687c66f5edfcfff085a42c27 (diff) |
logging: thread safety annotations
Adds LockGuard helper in threadsafety.h to replace lock_guard<mutex>
when LOCK(Mutex) isn't available for use.
Diffstat (limited to 'src')
-rw-r--r-- | src/logging.cpp | 6 | ||||
-rw-r--r-- | src/logging.h | 16 | ||||
-rw-r--r-- | src/threadsafety.h | 11 |
3 files changed, 23 insertions, 10 deletions
diff --git a/src/logging.cpp b/src/logging.cpp index eb9da06d9b..8ec05624ff 100644 --- a/src/logging.cpp +++ b/src/logging.cpp @@ -41,7 +41,7 @@ static int FileWriteStr(const std::string &str, FILE *fp) bool BCLog::Logger::StartLogging() { - std::lock_guard<std::mutex> scoped_lock(m_cs); + LockGuard scoped_lock(m_cs); assert(m_buffering); assert(m_fileout == nullptr); @@ -80,7 +80,7 @@ bool BCLog::Logger::StartLogging() void BCLog::Logger::DisconnectTestLogger() { - std::lock_guard<std::mutex> scoped_lock(m_cs); + LockGuard scoped_lock(m_cs); m_buffering = true; if (m_fileout != nullptr) fclose(m_fileout); m_fileout = nullptr; @@ -246,7 +246,7 @@ namespace BCLog { void BCLog::Logger::LogPrintStr(const std::string& str) { - std::lock_guard<std::mutex> scoped_lock(m_cs); + LockGuard scoped_lock(m_cs); std::string str_prefixed = LogEscapeMessage(str); if (m_log_threadnames && m_started_new_line) { diff --git a/src/logging.h b/src/logging.h index ab07010316..c55f581916 100644 --- a/src/logging.h +++ b/src/logging.h @@ -8,6 +8,7 @@ #include <fs.h> #include <tinyformat.h> +#include <threadsafety.h> #include <util/string.h> #include <atomic> @@ -62,9 +63,10 @@ namespace BCLog { { private: mutable std::mutex m_cs; // Can not use Mutex from sync.h because in debug mode it would cause a deadlock when a potential deadlock was detected - FILE* m_fileout = nullptr; // GUARDED_BY(m_cs) - std::list<std::string> m_msgs_before_open; // GUARDED_BY(m_cs) - bool m_buffering{true}; //!< Buffer messages before logging can be started. GUARDED_BY(m_cs) + + FILE* m_fileout GUARDED_BY(m_cs) = nullptr; + std::list<std::string> m_msgs_before_open GUARDED_BY(m_cs); + bool m_buffering GUARDED_BY(m_cs) = true; //!< Buffer messages before logging can be started. /** * m_started_new_line is a state variable that will suppress printing of @@ -79,7 +81,7 @@ namespace BCLog { std::string LogTimestampStr(const std::string& str); /** Slots that connect to the print signal */ - std::list<std::function<void(const std::string&)>> m_print_callbacks /* GUARDED_BY(m_cs) */ {}; + std::list<std::function<void(const std::string&)>> m_print_callbacks GUARDED_BY(m_cs) {}; public: bool m_print_to_console = false; @@ -98,14 +100,14 @@ namespace BCLog { /** Returns whether logs will be written to any output */ bool Enabled() const { - std::lock_guard<std::mutex> scoped_lock(m_cs); + LockGuard scoped_lock(m_cs); return m_buffering || m_print_to_console || m_print_to_file || !m_print_callbacks.empty(); } /** Connect a slot to the print signal and return the connection */ std::list<std::function<void(const std::string&)>>::iterator PushBackCallback(std::function<void(const std::string&)> fun) { - std::lock_guard<std::mutex> scoped_lock(m_cs); + LockGuard scoped_lock(m_cs); m_print_callbacks.push_back(std::move(fun)); return --m_print_callbacks.end(); } @@ -113,7 +115,7 @@ namespace BCLog { /** Delete a connection */ void DeleteCallback(std::list<std::function<void(const std::string&)>>::iterator it) { - std::lock_guard<std::mutex> scoped_lock(m_cs); + LockGuard scoped_lock(m_cs); m_print_callbacks.erase(it); } diff --git a/src/threadsafety.h b/src/threadsafety.h index bb988dfdfd..81f86eac3a 100644 --- a/src/threadsafety.h +++ b/src/threadsafety.h @@ -6,6 +6,8 @@ #ifndef BITCOIN_THREADSAFETY_H #define BITCOIN_THREADSAFETY_H +#include <mutex> + #ifdef __clang__ // TL;DR Add GUARDED_BY(mutex) to member variables. The others are // rarely necessary. Ex: int nFoo GUARDED_BY(cs_foo); @@ -54,4 +56,13 @@ #define ASSERT_EXCLUSIVE_LOCK(...) #endif // __GNUC__ +// LockGuard provides an annotated version of lock_guard for us +// should only be used when sync.h Mutex/LOCK/etc aren't usable +class SCOPED_LOCKABLE LockGuard : public std::lock_guard<std::mutex> +{ +public: + explicit LockGuard(std::mutex& cs) EXCLUSIVE_LOCK_FUNCTION(cs) : std::lock_guard<std::mutex>(cs) { } + ~LockGuard() UNLOCK_FUNCTION() {}; +}; + #endif // BITCOIN_THREADSAFETY_H |