Subject: [Boost-bugs] [Boost C++ Libraries] #9145: BOOST_LOG_FUNCTION + asynchronous_sink + UnloadLibrary = crash
From: Boost C++ Libraries (noreply_at_[hidden])
Date: 2013-09-21 13:03:17
#9145: BOOST_LOG_FUNCTION + asynchronous_sink + UnloadLibrary = crash
------------------------------+---------------------
Reporter: cnewbold | Owner: andysem
Type: Bugs | Status: new
Milestone: To Be Determined | Component: log
Version: Boost 1.54.0 | Severity: Problem
Keywords: |
------------------------------+---------------------
Full disclosure: this is admittedly an edge case and I have not actually
yet attempted reproduction against 1.54; I am using a somewhat earlier
version of Boost.Log. But code inspection of 1.54 suggests the issue
likely remains.
Our application is using BOOST_LOG_FUNCTION to track control flow and
Boost.Log is configured with an asynchronous_sink that is spooling log
records to disk in the background. We also heavily use dynamic libraries
for plug-ins: they are frequently loaded and unloaded during execution in
response to user input.
I am occasionally seeing crashes deep inside the log record formatting
machinery driven by the asynchronous_sink and have tracked the problem
down to the combination of BOOST_LOG_FUNCTION and the unloading of dynamic
libraries.
basic_named_scope_entry captures the function and file names using
basic_string_literal, which just hangs on to the character pointer
supplied during construction. BOOST_LOG_FUNCTION obtains function and file
names using built-in constants such as __FILE__, which just flow through
into the basic_named_scope_entries that comprise the current thread's
context. These string constants (at least with MSVC on Windows) are stored
in the dynamic library containing the code. So when a library is unloaded,
the pointed-to strings are no longer valid.
Digging deeper, the implementation of
named_scope_value::detach_from_thread() copies the scope list, but since
this is just a container of basic_string_literals, only ends up copying
the pointers to the literals and not the actual data. So FOO.DLL does some
logging with BOOST_LOG_FUNCTION, log records get queued in the
asynchronous_sink and then we unload FOO.DLL. Eventually the feeding
thread in the asynchronous_sink gets to processing these records and
crashes because the string literal pointers in the named scope list are
now invalid.
(Note that we are careful not to otherwise pass data by reference to
Boost.Log from FOO.DLL; all data is passed by value.)
One way to fix this would be to have
named_scope_value::detach_from_thread() make a true deep copy of the named
scope stack, including the string literals. More expensive, yes, but it
closes this hole where library clients can inadvertently queue records
with references to data.
-- Ticket URL: <https://svn.boost.org/trac/boost/ticket/9145> Boost C++ Libraries <http://www.boost.org/> Boost provides free peer-reviewed portable C++ source libraries.
This archive was generated by hypermail 2.1.7 : 2017-02-16 18:50:14 UTC