From 4bd25f897f1df1ac5e0d6902a5971e85e96c9eba Mon Sep 17 00:00:00 2001 From: gabi Date: Fri, 7 Nov 2014 16:17:53 +0200 Subject: [PATCH] async_sink: catch back thread exceptions and rethrow on the calling thread on the next logging request --- include/spdlog/sinks/async_sink.h | 60 ++++++++++++++++++++++++------- 1 file changed, 48 insertions(+), 12 deletions(-) diff --git a/include/spdlog/sinks/async_sink.h b/include/spdlog/sinks/async_sink.h index 67f3c8ac..ff625a01 100644 --- a/include/spdlog/sinks/async_sink.h +++ b/include/spdlog/sinks/async_sink.h @@ -22,6 +22,14 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +// async sink: +// Process logs asynchronously using a back thread. +// +// If the internal queue of log messages reaches its max size, +// then the client call will block until there is more room. +// +// If the back thread throws during logging, a spdlog::spdlog_ex exception +// will be thrown in client's thread when tries to log the next message #pragma once #include @@ -68,9 +76,17 @@ private: std::atomic _active; q_type _q; std::thread _back_thread; - //Clear all remaining messages(if any), stop the _back_thread and join it - void _join() ; std::mutex _mutex; + //Last exception thrown from the back thread + std::shared_ptr _last_backthread_ex; + + + //will throw last back thread exception or if backthread no active + void _push_sentry(); + + //Clear all remaining messages(if any), stop the _back_thread and join it + void _join(); + }; } } @@ -80,7 +96,7 @@ private: /////////////////////////////////////////////////////////////////////////////// inline spdlog::sinks::async_sink::async_sink(const q_type::size_type max_queue_size) :_sinks(), - _active(true), + _active(false), _q(max_queue_size), _back_thread(&async_sink::_thread_loop, this) {} @@ -92,14 +108,15 @@ inline spdlog::sinks::async_sink::~async_sink() inline void spdlog::sinks::async_sink::_sink_it(const details::log_msg& msg) { - if (!_active) - return; + _push_sentry(); _q.push(msg); } + inline void spdlog::sinks::async_sink::_thread_loop() { - static std::chrono::seconds pop_timeout { 1 }; + std::chrono::seconds pop_timeout { 1 }; + while (_active) { q_type::item_type msg; @@ -109,7 +126,20 @@ inline void spdlog::sinks::async_sink::_thread_loop() return; for (auto &s : _sinks) { - s->log(msg); + try + { + s->log(msg); + } + + catch (const std::exception& ex) + { + _last_backthread_ex = std::make_shared(ex.what()); + } + catch (...) + { + _last_backthread_ex = std::make_shared("Unknown exception"); + } + } } } @@ -149,10 +179,18 @@ inline void spdlog::sinks::async_sink::shutdown(const std::chrono::milliseconds& } +inline void spdlog::sinks::async_sink::_push_sentry() +{ + std::shared_ptr ex_copy = std::move(_last_backthread_ex); + if (ex_copy) + throw *ex_copy; + if (!_active) + throw(spdlog_ex("async_sink not active")); +} + inline void spdlog::sinks::async_sink::_join() { - std::lock_guard guard(_mutex); _active = false; if (_back_thread.joinable()) { @@ -160,11 +198,9 @@ inline void spdlog::sinks::async_sink::_join() { _back_thread.join(); } - catch (const std::system_error&) //Dont crush if thread not joinable - { - } + catch (const std::system_error&) //Dont crash if thread not joinable + {} } - }