async_sink: catch back thread exceptions and rethrow on the calling thread on the next logging request
This commit is contained in:
		@@ -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 <thread>
 | 
			
		||||
@@ -68,9 +76,17 @@ private:
 | 
			
		||||
    std::atomic<bool> _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<spdlog_ex> _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<spdlog_ex>(ex.what());
 | 
			
		||||
                }
 | 
			
		||||
                catch (...)
 | 
			
		||||
                {
 | 
			
		||||
                    _last_backthread_ex = std::make_shared<spdlog_ex>("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<spdlog_ex> 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<std::mutex> 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
 | 
			
		||||
        {}
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user