-
Notifications
You must be signed in to change notification settings - Fork 561
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Application using log4cplus hangs on exit #102
Comments
|
This is weird. I cannot see how could The only scenario where it could possibly happen is when your code is logging from static/global variables destructors or similar. In this situation it might happen that
You say:
This is by design. First threads that might be using the hierarchy are shut down and only then the hierarchy itself is destroyed.
I do not think this is a correct solution since it is unclear what is the actual cause. Please make sure that you are using the |
My understanding of the problem is the following: I definitely don't use logging from static/global destructors. I'll check what thread_test does and make additional check of my application. |
|
Below is excerpt from my code (works fine with log4cplus 1.x.x) to demonstrate the problem: #include <log4cplus/logger.h>
#include <log4cplus/loggingmacros.h>
#include <log4cplus/consoleappender.h>
/**
* Initialize logging framework.
*/
static void
initLogging()
{
using namespace log4cplus;
// Initialize log4cplus framework.
initialize();
LogLevelManager& log_man = getLogLevelManager();
Logger root_logger = Logger::getRoot();
// Manage log level.
root_logger.setLogLevel(DEBUG_LOG_LEVEL);
// Configure log output layout.
tstring pattern = LOG4CPLUS_TEXT("%D{%Y-%m-%d %H:%M:%S.%q} [%t] %-5p %c - %m%n");
// Manage logging to console.
SharedAppenderPtr console_ptr(new ConsoleAppender("test"));
console_ptr->setLayout(std::auto_ptr<Layout>(new PatternLayout(pattern)));
root_logger.addAppender(console_ptr);
LOG4CPLUS_INFO(root_logger, LOG4CPLUS_TEXT("Logger initialized"));
}
/**
*
*/
int main(int argc, char* argv[])
{
initLogging();
LOG4CPLUS_INFO(log4cplus::Logger::getRoot(), LOG4CPLUS_TEXT("test exited"));
return (0);
}Makefile: |
Hmm, this seems as plausible scenario. My initial thought, when I was writing the previous post, was that I wanted to shut down the thread pool so that possible concurrent logging thread would error out on Checking
So, the thread pool shutdown there has a meaning. Now, I wonder how it works on Windows with MSVC and does not on Linux (?) with GCC? I could remove the line from Checking GCC 4.8's // Destructor.
~unique_ptr() noexcept
{
auto& __ptr = std::get<0>(_M_t);
if (__ptr != nullptr)
get_deleter()(__ptr);
__ptr = pointer();
}And this for void
reset(pointer __p = pointer()) noexcept
{
using std::swap;
swap(std::get<0>(_M_t), __p);
if (__p != pointer())
get_deleter()(__p);
}IOW, even when the TL;DR, I still do not get it. :) |
|
Well, UB is never a good thing, so let's try with this now: diff --git a/src/hierarchy.cxx b/src/hierarchy.cxx
index dc0f7fd..a9efd25 100644
--- a/src/hierarchy.cxx
+++ b/src/hierarchy.cxx
@@ -235,13 +235,11 @@ Hierarchy::getLoggerFactory()
// from global-init.cxx
void waitUntilEmptyThreadPoolQueue ();
-void shutdownThreadPool ();
void
Hierarchy::shutdown()
{
waitUntilEmptyThreadPoolQueue ();
- shutdownThreadPool ();
LoggerList loggers = getCurrentLoggers();
Does this fix your problem? |
|
Yes, I've forgot to mention that I'm using log4cplus for Linux, gcc version 5.1.1. Your fix works fine for me. |
Do not tear down thread pool on `Hierarchy::shutdown()`.
|
Irrespective of whether removing the call to shutdownThreadPool was a fix of some sort, I believe serlin74's original suggestion, that the order of the members of the DefaultContext struct needs to be changed, is correct. Building the master on Visual Studio 2015 64-bit in Debug, most of the test applications crash on exit with an invalid memory access while trying to wait an an already destructed thread pool during destruction of the static DefaultContext instance. The hierarchy member destructor is currently called after the thread pool is destroyed, which calls into the thread pool instance through ~Hierarchy() -> shutdown() -> waitUntilEmptyThreadPoolQueue(). To address this problem and prevent future issues, the thread pool member should be moved above any other member that uses it or is likely to use it in the future, especially during destruction. Please see http://stackoverflow.com/questions/2254263/order-of-member-constructor-and-destructor-calls |
Is this not fixed by 13027c3? |
|
No, that change actually makes this issue more pronounced as waitUntilEmptyThreadPoolQueue now enters into the 'if (dc->thread_pool)' block after the thread_pool is destroyed during DefaultContext destruction (due to thread_pool's order relative to hierarchy). Where as with the code prior to that change, thread_pool (its unique_ptr) would have been null the second time through if it was destroyed via the reset call. You should see the current problem pretty quickly with any debug build on a platform that marks freed memory. It's unlikely to show in a release build. |
|
Also, FYI, re the original problem. There were (are?) incorrect implementations of unique_ptr on multiple compilers that can cause a double delete. |
|
@rwightman If you are using Visual Studio, then try to change your application so that it conforms to the requirements described at |
The problem is not with |
|
I read the README.md, the crash is occurring in debug for most of the included test apps on exit. It is not related to anything I'm doing with my own code. |
|
@rwightman OK, I will have to look again. I thought it was working well after the fixes. |
|
@rwightman I have not reproduced the exit issue that you have mentioned. Unfortunately I have reproduced a different issue on start up. I have pushed two changes to fix it. First, wilx@f34a58f, to fix issue with initialization using APC callbacks when log4cplus was used as a static library. Second, d7aa378, to fix tests to use Does this solve all of your issues? |
|
@rwightman Ping. |
|
@rwightman I have recently fixed another at exit crash: #155. Does it by a chance also resolve your issue? |
|
I am closing this issue as fixed. If you think otherwise, please reopen this issue or fill a new one. |
|
Hi, same problem here. VS2015, WinForm x64 application (C#), C++ dll that references log4cplus, Debug, crashes (Access violation) on exit, . The workaround was to call explicitly Logger::shutdown and comment waitUntilEmptyThreadPoolQueue in Hierarchy::shutdown() (blindly, I don't know if it leads to any memory leak or other issues). Regards. |
|
@federicozanco commented on 29. 6. 2017 13:08 SELČ:
Could you please test the solution proposed in the following comment thread? da36fd8#commitcomment-22810107 |
|
after a quick test seems working. Didn't tried with Initializer though. |
|
I have pushed dedbec4 to 2.0.x branch to implement this. I really hope this will fix this issue finally. Please reopen this issue if it still is a problem. |
|
I am getting the same error on 2.0.x If I convert all my projects to static libraries + exes, however, the issue goes away. This isn't ideal, of course. ETA: Visual Studio 2017, C++14/17 |
With relatively latest log4cplus version (commit from 04122015) I have encountered unexpected hang in my application upon exit. After two days of digging, I have found that ThreadPool destructor is called twice:
As you can see, all worker threads have gone. And the second one:
As you can see log4cplus::Hierarchy::shutdown tries to destruct already destructed ThreadPool instance. It happens because of fields order in struct DefaultContext (from global-init.cxx):
thread_pool member is destructed before hierarchy member. As result, we are in trouble. Several solutions possible:
The text was updated successfully, but these errors were encountered: