Hi folks,
I recently started using log4cxx (from the svn trunk). Thanks for the great
work. It is easily the most featureful logging framework out there, althout
the Java legacy makes it somewhat awkward to use in the C++ world.
I wanted to be able to run my executables with different log configuration
files for different tasks such as performance evaluation or debugging, and
thus wanted to be able to pass the configuration file name to use as a
command line option. The problem is that there is no mechanism in the
log4cxx::PropertyConfigurator::configure() method that allows me to check for
failure of the configuration. If the file cannot be read or is malformed,
I'll get an error message to the console but nothing else. So I checked the
source code and saw that the doConfigure method actually uses exceptions
(albeit is not exception-safe) but chooses to not let the exception propagate
up the call stack to let the user handle it (which is one of the main reasons
for using exceptions in the first place). So I decided to remove the
try-catch blocks from the code so I could handle the exceptions myself like
this:
try{
// try to configure the logger with the given filename
// if the file could not be processed, we'll get an exception
// CAUTION: This relies on a patch to the
// propertyconfigurator.cpp file of log4cxx
log4cxx::PropertyConfigurator::configure(log_cfg_filename);
}
catch (std::exception &e){
// do nothing, stay with default
}
That didn't work as I thought as the code is not exception safe. Before it
even enters its own try block, it sets the hierarchy configured state to
true:
hierarchy->setConfigured(true);
When an exception is thrown, this either needs to be reverted in the catch
blocks, or - easier yet - set the configured state *after* the configuration
was successful.
The following patch does just that: lets the exceptions propagate up the call
stack and makes the method exception-safe by setting the hierarchy only after
success:
=== begin patch ===
Index: src/propertyconfigurator.cpp
===================================================================
--- src/propertyconfigurator.cpp (revision 448948)
+++ src/propertyconfigurator.cpp (working copy)
@@ -81,24 +81,11 @@
void PropertyConfigurator::doConfigure(const File& configFileName,
spi::LoggerRepositoryPtr& hierarchy)
{
- hierarchy->setConfigured(true);
-
Properties props;
- try {
- InputStreamPtr inputStream = new FileInputStream(configFileName);
- props.load(inputStream);
- } catch(const IOException& ie) {
- LogLog::error(((LogString) LOG4CXX_STR("Could not read
configuration file ["))
- + configFileName.getName() + LOG4CXX_STR("]."));
- return;
- }
-
- try {
- doConfigure(props, hierarchy);
- } catch(const std::exception& ex) {
- LogLog::error(((LogString) LOG4CXX_STR("Could not parse
configuration file ["))
- + configFileName.getName() + LOG4CXX_STR("]."), ex);
- }
+ InputStreamPtr inputStream = new FileInputStream(configFileName);
+ props.load(inputStream);
+ doConfigure(props, hierarchy);
+ hierarchy->setConfigured(true);
}
void PropertyConfigurator::configure(const File& configFilename)
=== end patch ===
There's also a bug in Logger::getLogger(): it trashes the system (eating up
memory until it dies) when being accidentally passed a name with a leading
"." (dot). I'll try to file that as a bug.
Best regards,
Jens
--
Dr.-Ing. Jens Hannemann --- [EMAIL PROTECTED] --- GPG Key Available
University of Kentucky -- Dept. of Electrical and Computer Engineering
Center for Visualization and Virtual Environments