Boost C++ Libraries: Ticket #9145: BOOST_LOG_FUNCTION + asynchronous_sink + UnloadLibrary = crash https://svn.boost.org/trac10/ticket/9145 <p> 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. </p> <p> 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. </p> <p> 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. </p> <p> 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. </p> <p> 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. </p> <p> (Note that we are careful not to otherwise pass data by reference to Boost.Log from FOO.DLL; all data is passed by value.) </p> <p> 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. </p> en-us Boost C++ Libraries /htdocs/site/boost.png https://svn.boost.org/trac10/ticket/9145 Trac 1.4.3 Chris Newbold Sat, 21 Sep 2013 13:05:40 GMT description changed https://svn.boost.org/trac10/ticket/9145#comment:1 https://svn.boost.org/trac10/ticket/9145#comment:1 <ul> <li><strong>description</strong> modified (<a href="/trac10/ticket/9145?action=diff&amp;version=1">diff</a>) </li> </ul> Ticket Andrey Semashev Sat, 21 Sep 2013 15:32:27 GMT status changed; resolution set https://svn.boost.org/trac10/ticket/9145#comment:2 https://svn.boost.org/trac10/ticket/9145#comment:2 <ul> <li><strong>status</strong> <span class="trac-field-old">new</span> → <span class="trac-field-new">closed</span> </li> <li><strong>resolution</strong> → <span class="trac-field-new">wontfix</span> </li> </ul> <p> This is a known and <a href="http://www.boost.org/doc/libs/release/libs/log/doc/html/log/detailed/sink_frontends.html#log.detailed.sink_frontends.async">documented</a> limitation of the library. String literals are not the only thing that can be referred to by the library by references. For example, references to type info data can pose a similar problem. Therefore the library does not protect from unloading modules, you either have to avoid unloading them or to make sure no references are left to the unloaded module. </p> Ticket