Git Product home page Git Product logo

Comments (13)

0x61726b avatar 0x61726b commented on May 27, 2024

Also realized that if I build log4cplus as static library(BUILD_SHARED_LIBS is false), now it doesnt crash but hangs at native exit function.

#if !defined (_KERNELX)
            _tinitenv = _tenviron;
            mainret = _tmain(__argc, _targv, _tenviron);
#else  /* !defined (_KERNELX) */
            mainret = _tmain(0, NULL, NULL);
#endif  /* !defined (_KERNELX) */
#endif  /* _WINMAIN_ */

            if ( !managedapp )
                exit(mainret); <-------------- HANGS HERE

            _cexit();

With debugging I saw that now Hierarchy::shutdown() is not being called

from log4cplus.

wilx avatar wilx commented on May 27, 2024

Is this the master branch version? If it is, use log4cplus::Initializer initializer; instead of calling log4cplus::initialize();

from log4cplus.

0x61726b avatar 0x61726b commented on May 27, 2024

Oh wow, I should have checked the tests , I simply followed the wiki on the sourceforge. Thanks for the quick response, it works now!

from log4cplus.

0x61726b avatar 0x61726b commented on May 27, 2024

I'm reopening this since I can't quite figure out why things dont work with log4cplus.

  • Msvc Vs2013 x64 Debug
  • master branch of log4cplus
  • log4cplus as static library compiled with /MDd

I'm initializing log4cplus from a shared library compiled with /MDd. I have reduced the code to minimalize it to be able to post here so here is my code

First the main function in the executable,

namespace YumeEngine
{
#if defined(_MSC_VER)
#define YUME_MAIN(function) \
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance, LPSTR cmdLine, int showCmd) \
{ \
    YumeEngine::ParseArguments(GetCommandLineA()); \
    return function; \
}
#else
#define YUME_MAIN(function) \
int main(int argc, char** argv) \
{ \
    YumeEngine::ParseArguments(argc, argv); \
    return function; \
}
#endif
}

#define YUME_DEFINE_ENTRY_POINT(className) \
int RunApplication() \
    { \
    boost::shared_ptr<className> application(new className); \
    return application->Run(); \
    } \
YUME_MAIN(RunApplication());



....

YUME_DEFINE_ENTRY_POINT(YumeEngine::HelloWorld);

HelloWorld inherits from the application class and creates a engine pointer

    YumeApplication::YumeApplication()
        : exitCode_(0)
    {
        engine_ = boost::shared_ptr<YumeEngine3D>(new YumeEngine3D);
    }

The run function

    int YumeApplication::Run()
    {
        Setup();

        if(!engine_->Initialize(engineVariants_))
        {
            exitCode_ = -1;
            return exitCode_;
        }


        Start();
        if(exitCode_ == 1)
            return exitCode_;

#ifndef YUME_TEST_MODE
        while(!engine_->IsExiting())
            engine_->Run();
#else
        if(!engine_->IsExiting())
            engine_->Run();
#endif
        engine_->Exit();

        return exitCode_;
    }

Now the initialize function which has the log4cplus stuff

bool YumeEngine3D::Initialize(const VariantMap& variants)
{
//Initialize other stuff
    log4cplus::initialize()
    YumeEngine::Log::InitLogging(env_->GetLogFile().generic_string().c_str());
}

InitLogging function


void YumeEngine::Log::InitLogging(const char* loc)
{
    loggingEnabled = true;

#if YUME_PLATFORM == YUME_PLATFORM_WIN32
    log4cplus::SharedAppenderPtr debugAppender(new log4cplus::Win32ConsoleAppender());
    debugAppender->setName(LOG4CPLUS_TEXT("First"));
    debugAppender->setLayout(std::unique_ptr<log4cplus::Layout>(new log4cplus::SimpleLayout()));
    log4cplus::Logger::getRoot().addAppender(debugAppender);
#else
    log4cplus::SharedAppenderPtr debugAppender(new log4cplus::ConsoleAppender());
    debugAppender->setName(LOG4CPLUS_TEXT("ConsoleAppender"));
    debugAppender->setLayout(std::unique_ptr<log4cplus::Layout>(new log4cplus::TTCCLayout()));
    log4cplus::Logger::getRoot().addAppender(debugAppender);
#endif

    std::string strModulePath = std::string(loc);
    const size_t cSize = strlen(loc);
    std::wstring wstrModulePath(cSize, L'#');
    mbstowcs(&wstrModulePath[0], loc, cSize);

#if YUME_PLATFORM == YUME_PLATFORM_WIN32
    log4cplus::SharedAppenderPtr fileAppender(new log4cplus::RollingFileAppender(wstrModulePath));
#else
    log4cplus::SharedAppenderPtr fileAppender(new log4cplus::RollingFileAppender(strModulePath));
#endif

    fileAppender->setName(LOG4CPLUS_TEXT("Second"));
    fileAppender->setLayout(
        std::unique_ptr<log4cplus::Layout>(
        new log4cplus::PatternLayout(LOG4CPLUS_TEXT("[%-5p][%D{%Y/%m/%d %H:%M:%S:%q}][%t] %m%n"))));
    log4cplus::Logger::getRoot().addAppender(fileAppender);

}

void YumeEngine::Log::StopLogging()
{
      log4cplus::Logger::shutdown();

    ToggleLogging(false);



}

Exit function

void YumeEngine3D::Exit()
{
//other stuff
    YumeEngine::Log::StopLogging();
}

No log4cplus functions are called after the Exit().

With this setup, Win32 console and file appender works just fine, but it crashes while trying to lock a mutex on exit.

>   msvcp120d.dll!mtx_do_lock(_Mtx_internal_imp_t * * mtx, const xtime * target) Line 49    C++
    msvcp120d.dll!_Mtx_lock(_Mtx_internal_imp_t * * mtx) Line 154   C++
    YumeEngine.dll!std::_Mtx_lockX(_Mtx_internal_imp_t * * _Mtx) Line 68    C++
    YumeEngine.dll!std::_Mutex_base::lock() Line 42 C++
    YumeEngine.dll!std::unique_lock<std::mutex>::unique_lock<std::mutex>(std::mutex & _Mtx) Line 220    C++
    YumeEngine.dll!progschj::ThreadPool::wait_until_empty() Line 192    C++
    YumeEngine.dll!log4cplus::waitUntilEmptyThreadPoolQueue() Line 298  C++
    YumeEngine.dll!log4cplus::Hierarchy::shutdown() Line 244    C++
    YumeEngine.dll!log4cplus::Hierarchy::~Hierarchy() Line 81   C++
    YumeEngine.dll!log4cplus::`anonymous namespace'::DefaultContext::~DefaultContext()  C++
    YumeEngine.dll!log4cplus::`anonymous namespace'::DefaultContext::`scalar deleting destructor'(unsigned int) C++
    YumeEngine.dll!log4cplus::`anonymous namespace'::destroy_default_context::~destroy_default_context() Line 166   C++
    YumeEngine.dll!log4cplus::`anonymous namespace'::`dynamic atexit destructor for 'destroy_default_context_''()   C++
    YumeEngine.dll!_CRT_INIT(void * hDllHandle, unsigned long dwReason, void * lpreserved) Line 416 C
    YumeEngine.dll!__DllMainCRTStartup(void * hDllHandle, unsigned long dwReason, void * lpreserved) Line 522   C
    YumeEngine.dll!_DllMainCRTStartup(void * hDllHandle, unsigned long dwReason, void * lpreserved) Line 473    C
    ntdll.dll!LdrpCallInitRoutine() Unknown
    ntdll.dll!LdrShutdownProcess()  Unknown
    ntdll.dll!RtlExitUserProcess()  Unknown
    kernel32.dll!ExitProcessImplementation�()   Unknown
    msvcr120d.dll!__crtExitProcess(int status) Line 776 C
    msvcr120d.dll!doexit(int code, int quick, int retcaller) Line 679   C
    msvcr120d.dll!exit(int code) Line 426   C
    HelloWorld.exe!__tmainCRTStartup() Line 662 C
    HelloWorld.exe!WinMainCRTStartup() Line 466 C
    kernel32.dll!BaseThreadInitThunk�() Unknown
    ntdll.dll!RtlUserThreadStart()  Unknown

Now weirdly enough if I put log4cplus::Initializer initializer; in the Initialize() _without_ removing log4cplus::initialize() it doesnt crash. It must be a false positive since when my Initialize() function exits the destructor of log4cplus::Initializer is called..

So it doesnt crash like this

bool YumeEngine3D::Initialize(const VariantMap& variants)
{
//Initialize other stuff
    log4cplus::Initializer initializer;
    log4cplus::initialize()
    YumeEngine::Log::InitLogging(env_->GetLogFile().generic_string().c_str());
}

Doesnt crash like this too,

bool YumeEngine3D::Initialize(const VariantMap& variants)
{
//Initialize other stuff
    log4cplus::Initializer initializer;
    YumeEngine::Log::InitLogging(env_->GetLogFile().generic_string().c_str());
}

This is obviously wrong but may give someone a hint.

from log4cplus.

wilx avatar wilx commented on May 27, 2024

I suggest that you just put log4cplus::Initializer initializer; at the top of your main() or WinMain(), if you are using log4cplus for the whole application. If you want to just use it for your YumEngine3D class, then I suggest you add it as a member.

I guess I should note that once log4cplus shuts down, I do not think it is possible to re-start it by using the initializer again.

from log4cplus.

0x61726b avatar 0x61726b commented on May 27, 2024

I already tried putting it in the top of the main but the outcome did not change.Weird. And I want to be able to turn off logging with a command line argument so putting it as a member or on top of main doesnt seem good for that reason. Maybe put log4cplus::Initializer initializer; in the class as a pointer?

from log4cplus.

0x61726b avatar 0x61726b commented on May 27, 2024

Putting log4cplus::Initializer* initializer_; as a member pointer works,but it kind of defeats the purpose of the log4cplus::Initializer class?

Now I can write like this and there is no problem

In the YumeEngine3D::Initialize()

if(env_->GetVariant("enableLogging").Get<bool>())
        {
            log4cplusinitializer_ = new log4cplus::Initializer;
            YumeEngine::Log::InitLogging(env_->GetLogFile().generic_string().c_str());
        }

And when exiting,

StopLogging()
delete log4cplusinitializer_;

from log4cplus.

wilx avatar wilx commented on May 27, 2024

Putting log4cplus::Initializer* initializer_; as a member pointer works,but it kind of defeats the purpose of the log4cplus::Initializer class?

Yes, that defeats the purpose.

Handle the disabling of the logging by log levels and thresholds or filter settings.

from log4cplus.

wilx avatar wilx commented on May 27, 2024

I suggest that you just put log4cplus::Initializer initializer; at the top of your main() or WinMain(), if you are using log4cplus for the whole application. If you want to just use it for your YumEngine3D class, then I suggest you add it as a member.

I guess I should note that once log4cplus shuts down, I do not think it is possible to re-start it by using the initializer again.

from log4cplus.

flyish avatar flyish commented on May 27, 2024

hi, I have the same problem, crash at threadpool::~threadpool when close loggingserver, Hierarchy not yet execute, stack trace :

 	ntdll.dll!_TpAllocWait@16�()
 	kernel32.dll!_CreateThreadpoolWait@12�()
>	msvcr120d.dll!__crtCreateThreadpoolWait(void (_TP_CALLBACK_INSTANCE *, void *, _TP_WAIT *, unsigned long) * pfnwa, void * pv, _TP_CALLBACK_ENVIRON_V1 * pcbe) 行 582	C
 	msvcr120d.dll!Concurrency::details::RegisterAsyncWaitAndLoadLibrary(void * waitingEvent, void (_TP_CALLBACK_INSTANCE *, void *, _TP_WAIT *, unsigned long) * callback, void * data) 行 673	C++
 	msvcr120d.dll!Concurrency::details::ExternalContextBase::PrepareForUse(bool explicitAttach) 行 120	C++
 	msvcr120d.dll!Concurrency::details::ExternalContextBase::ExternalContextBase(Concurrency::details::SchedulerBase * pScheduler, bool explicitAttach) 行 48	C++
 	msvcr120d.dll!Concurrency::details::SchedulerBase::GetExternalContext(bool explicitAttach) 行 1634	C++
 	msvcr120d.dll!Concurrency::details::SchedulerBase::AttachExternalContext(bool explicitAttach) 行 1582	C++
 	msvcr120d.dll!Concurrency::details::SchedulerBase::CreateContextFromDefaultScheduler() 行 573	C++
 	msvcr120d.dll!Concurrency::details::SchedulerBase::CurrentContext() 行 402	C++
 	msvcr120d.dll!Concurrency::details::LockQueueNode::LockQueueNode(unsigned int timeout) 行 619	C++
 	msvcr120d.dll!Concurrency::critical_section::lock() 行 1026	C++
 	msvcp120d.dll!mtx_do_lock(_Mtx_internal_imp_t * * mtx, const xtime * target) 行 67	C++
 	msvcp120d.dll!_Mtx_lock(_Mtx_internal_imp_t * * mtx) 行 153	C++
 	log4cplus.dll!std::_Mtx_lockX(_Mtx_internal_imp_t * * _Mtx) 行 68	C++
 	log4cplus.dll!std::_Mutex_base::lock() 行 41	C++
 	log4cplus.dll!std::unique_lock<std::mutex>::unique_lock<std::mutex>(std::mutex & _Mtx) 行 220	C++
 	log4cplus.dll!progschj::ThreadPool::~ThreadPool() 行 179	C++

from log4cplus.

MaksymB avatar MaksymB commented on May 27, 2024

If it is expected (at least under Visual Studio) that the library will be shut down before destroy_default_context::~destroy_default_context() is called, then it would be logical to log a short message to give a hint what is going wrong.
Here is what I did locally:

diff --git a/src/global-init.cxx b/src/global-init.cxx
index 9a8db64a..50937dc5 100644
--- a/src/global-init.cxx
+++ b/src/global-init.cxx
@@ -163,6 +163,16 @@ struct destroy_default_context
 {
     ~destroy_default_context ()
     {
+#if ! defined (LOG4CPLUS_SINGLE_THREADED) && defined (_MSC_VER)
+        if (default_context->thread_pool != nullptr)
+        {
+            helpers::getLogLog().error(
+                LOG4CPLUS_TEXT("Thread pool must be shut down by now. Missed an instance of "\
+                               "`log4cplus::Initializer` at the top of main function?"));
+            return;
+        }
+#endif
+
         delete default_context;
         default_context = nullptr;
         default_context_state = DC_DESTROYED;
--  

from log4cplus.

wilx avatar wilx commented on May 27, 2024

I have just merged recent changes to 2.0.x branch. Please try it if it fixes your log4cplus issues.

from log4cplus.

MaksymB avatar MaksymB commented on May 27, 2024

Revision f69f588 seems to fix the problem.
Thanks!

from log4cplus.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.