You are viewing a plain text version of this content. The canonical link for it is here.
Posted to log4cxx-user@logging.apache.org by Rhys Ulerich <rh...@gmail.com> on 2011/02/27 20:25:47 UTC
Static destruction fiasco?
Hi,
I've noticed that this little test program segfaults beautifully under 0.10
#include <log4cxx/logger.h>
log4cxx::LoggerPtr logger;
int main()
{
logger = log4cxx::Logger::getLogger("someName");
LOG4CXX_WARN(logger, "Stuffstuffstuff");
// logger = 0;
return 0;
}
but if I uncomment the "logger = 0" statement it runs just fine. Presumably
that's because "logger = 0" forces the ObjectPtrT instance behind LoggerPtr to
destruct logger before other static destruction occurs.
That said, which of
1) Bug
2) Don't do that
does that segfault fall into?
Thanks,
Rhys
Re: Static destruction fiasco?
Posted by Curt Arnold <ca...@apache.org>.
On Feb 27, 2011, at 1:25 PM, Rhys Ulerich wrote:
> Hi,
>
> I've noticed that this little test program segfaults beautifully under 0.10
>
> #include <log4cxx/logger.h>
>
> log4cxx::LoggerPtr logger;
>
> int main()
> {
> logger = log4cxx::Logger::getLogger("someName");
> LOG4CXX_WARN(logger, "Stuffstuffstuff");
> // logger = 0;
> return 0;
> }
>
> but if I uncomment the "logger = 0" statement it runs just fine. Presumably
> that's because "logger = 0" forces the ObjectPtrT instance behind LoggerPtr to
> destruct logger before other static destruction occurs.
>
> That said, which of
> 1) Bug
> 2) Don't do that
> does that segfault fall into?
>
> Thanks,
> Rhys
I'm guessing that you are running on a 64-bit Linux? The problem is that the "smart" pointer assignment should be atomic and that APR did not have a pointer exchange method at the time that the code (in this case src/main/cpp/objectptr.cpp) was written. If the platform was not Windows and not 32-bit, then APR mutexes were used to synchronize the operation (no longer the case).
The problem occurs when APR is terminated prior to pointer destruction. This will only occur when a static pointer is constructed prior to APR being initialized. The pointer class assumes that APR has already been initialized prior to the constructor. In general, you would expect to see code like:
log4cxx::LoggerPtr logger(log4cxx::Logger::getLogger("someName"));
In that case, APR is initialized prior to to the LoggerPtr::LoggerPtr class, so APR will be terminated after the LoggerPtr is destructed.
There are a couple of ways to avoid the issue that you've encountered:
a) Do not use the default constructor for static variables.
b) If you really want to use the default constructor for a static variable, explicitly trigger APR initialization prior to the default constructors
APRInitializer::initialize();
log4cxx::LoggerPtr logger;
c) Use the SVN HEAD where 64-bit exchange no longer uses APR mutexes to synchronize pointer exchanges.
Or any combination of the above.
Re: Static destruction fiasco?
Posted by Rhys Ulerich <rh...@gmail.com>.
> I've noticed that this little test program segfaults beautifully under 0.10
The "logger = 0" fix from my last email of course assumes regular program exit.
In case anyone wants something a little cleaner, atexit() can save you when
your program unwinds for other reasons:
#include <cstdlib>
#include <log4cxx/logger.h>
static log4cxx::LoggerPtr logger;
static struct DestructLoggerRegistration {
DestructLoggerRegistration() { atexit(&destruct_logger); }
static void destruct_logger() { logger = 0; }
} destructLoggerRegistration;
int main()
{
logger = log4cxx::Logger::getLogger("someName");
LOG4CXX_WARN(logger, "Stuffstuffstuff");
return 0;
}
where (at least for me) atexit() seems to make its callbacks prior to
static instance destruction occurs.
- Rhys