Hi Team,
I am experiencing a core dump when running a sample program with*
log4cxx-1.7.0*. Interestingly, the same program runs successfully using
*log4cxx-0.10.0*.
I have attached the sample code (*sample_log4cxx.cpp*) and the
configuration XML file(*Log4cxxConfig.xml*) for your review.
*Environment Details:*
OS: *Oracle Linux Server 8.8*
GCC Version: *8.5.0 20210514 (Red Hat 8.5.0-18.0.2)*
Compiler: *Intel(R) oneAPI DPC++/C++ Compiler 2025.2.1*
Compilation Command:
icpx -std=c++17 sample_log4cxx.cpp -I/opt/apache/log4cxx-1.7.0/include
-L/opt/apache/log4cxx-1.7.0/lib -llog4cxx -lapr-1 -laprutil-1 -o
sample_log4cxx
Please let me know if there are any specific configurations I am missing or
if you need additional debug logs (such as a GDB backtrace).
Should I proceed with logging a formal defect on your GitHub Issues page(
https://github.com/apache/logging-log4cxx/issues)?
I appreciate your quick support on this matter.
Best regards,
Pravas
// sample_log4cxx.cpp
#include <iostream>
#include <string>
#include <log4cxx/appenderskeleton.h>
#include <log4cxx/asyncappender.h>
#include <log4cxx/helpers/class.h>
#include <log4cxx/helpers/loglog.h>
#include <log4cxx/helpers/pool.h>
#include <log4cxx/helpers/stringhelper.h>
#include <log4cxx/helpers/transcoder.h>
#include <log4cxx/logger.h>
#include <log4cxx/logmanager.h>
#include <log4cxx/patternlayout.h>
#include <log4cxx/xml/domconfigurator.h>
#if !defined(LOG4CXX)
#define LOG4CXX 1
#endif
#include <log4cxx/private/log4cxx_private.h>
using namespace log4cxx;
using namespace log4cxx::helpers;
using namespace log4cxx::spi;
static std::string ToUtf8(const LogString& s) {
std::string out;
Transcoder::encode(s, out);
return out;
}
static void Stage(const std::string& msg) {
std::cout << "[sample_log4cxx] " << msg << std::endl;
}
class SampleDBAppender : public log4cxx::AppenderSkeleton {
public:
DECLARE_LOG4CXX_OBJECT(SampleDBAppender)
BEGIN_LOG4CXX_CAST_MAP()
LOG4CXX_CAST_ENTRY(SampleDBAppender)
LOG4CXX_CAST_ENTRY(log4cxx::Appender)
LOG4CXX_CAST_ENTRY(log4cxx::spi::OptionHandler)
LOG4CXX_CAST_ENTRY_CHAIN(log4cxx::AppenderSkeleton)
END_LOG4CXX_CAST_MAP()
SampleDBAppender() : mClosed(false) {}
~SampleDBAppender() override { close(); }
void setOption(const LogString& option, const LogString& value) override {
std::cout << "[SampleDBAppender::setOption] " << ToUtf8(option) << "="
<< ToUtf8(value) << std::endl;
if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("DBBRAND"),
LOG4CXX_STR("dbbrand"))) {
mDbBrand = value;
} else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("SQL"),
LOG4CXX_STR("sql"))) {
mSql = value;
} else if (StringHelper::startsWith(option, LOG4CXX_STR("SQL_"))) {
if (!mDbBrand.empty()) {
LogString expected = LOG4CXX_STR("SQL_");
expected.append(mDbBrand);
if (StringHelper::equalsIgnoreCase(option, expected,
StringHelper::toLowerCase(expected))) {
mSql = value; // SQL_POSTGRESQL etc.
}
}
} else {
AppenderSkeleton::setOption(option, value);
}
}
bool requiresLayout() const override { return true; }
void activateOptions(Pool& p) override {
AppenderSkeleton::activateOptions(p);
std::cout << "[SampleDBAppender::activateOptions] DBBRAND=" <<
ToUtf8(mDbBrand)
<< " SQL_SELECTED=" << ToUtf8(mSql) << std::endl;
}
void close() override { mClosed = true; }
protected:
void append(const LoggingEventPtr& event, Pool& p) override {
if (mClosed) return;
LogString out;
if (!mSql.empty()) {
PatternLayout layout;
layout.setConversionPattern(mSql);
layout.format(out, event, p);
} else if (getLayout()) {
getLayout()->format(out, event, p);
} else {
out = event->getRenderedMessage();
}
std::cout << "[SampleDBAppender::append] " << ToUtf8(out) << std::endl;
}
private:
bool mClosed;
LogString mDbBrand;
LogString mSql;
};
IMPLEMENT_LOG4CXX_OBJECT(SampleDBAppender)
LOG4CXX_PTR_DEF(SampleDBAppender);
class SampleASyncAppender : public log4cxx::AsyncAppender {
public:
DECLARE_LOG4CXX_OBJECT(SampleASyncAppender)
BEGIN_LOG4CXX_CAST_MAP()
LOG4CXX_CAST_ENTRY(SampleASyncAppender)
LOG4CXX_CAST_ENTRY(log4cxx::Appender)
LOG4CXX_CAST_ENTRY(log4cxx::spi::OptionHandler)
LOG4CXX_CAST_ENTRY_CHAIN(log4cxx::AsyncAppender)
END_LOG4CXX_CAST_MAP()
SampleASyncAppender() {}
~SampleASyncAppender() override { close(); }
void setOption(const LogString& option, const LogString& value) override {
std::cout << "[SampleASyncAppender::setOption] " << ToUtf8(option) <<
"=" << ToUtf8(value) << std::endl;
// Mirror wlserver custom-appender parsing behavior:
// consume known options and ignore unknown ones.
if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("DSN"),
LOG4CXX_STR("dsn"))) {
mDsn = value;
} else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("USER"),
LOG4CXX_STR("user"))) {
mUser = value;
} else if (StringHelper::equalsIgnoreCase(option,
LOG4CXX_STR("PASSWORD"), LOG4CXX_STR("password"))) {
mPassword = value;
} else if (StringHelper::equalsIgnoreCase(option,
LOG4CXX_STR("DBBRAND"), LOG4CXX_STR("dbbrand"))) {
mDbBrand = value;
} else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("SQL"),
LOG4CXX_STR("sql"))) {
mSql = value;
} else if (StringHelper::startsWith(option, LOG4CXX_STR("SQL_")) ||
StringHelper::startsWith(option, LOG4CXX_STR("INSERTSQL_")))
{
// keep for parity; not executed in this sample
} else {
// intentionally ignored (ex: BLOCKING, BUFFERSIZE)
}
}
void activateOptions(Pool& p) override {
std::cout << "[SampleASyncAppender::activateOptions] enter" <<
std::endl;
AsyncAppender::activateOptions(p);
std::cout << "[SampleASyncAppender::activateOptions] done" << std::endl;
}
private:
LogString mDsn;
LogString mUser;
LogString mPassword;
LogString mDbBrand;
LogString mSql;
};
IMPLEMENT_LOG4CXX_OBJECT(SampleASyncAppender)
LOG4CXX_PTR_DEF(SampleASyncAppender);
int main(int argc, char** argv) {
if (argc < 2) {
std::cerr << "Usage: " << argv[0] << " /path/to/Log4cxxConfig.xml\n";
return 1;
}
const std::string configPath = argv[1];
Stage("Program started");
Stage("Input config: " + configPath);
Stage("Registering classes");
SampleDBAppender::registerClass();
SampleASyncAppender::registerClass();
Stage("Enabling internal log4cxx debug");
log4cxx::helpers::LogLog::setInternalDebugging(true);
Stage("Calling DOMConfigurator::configure()");
try {
log4cxx::xml::DOMConfigurator::configure(configPath.c_str());
} catch (const std::system_error& ex) {
std::cerr << "[sample_log4cxx] std::system_error from configure: " <<
ex.what() << std::endl;
return 10;
} catch (const std::exception& ex) {
std::cerr << "[sample_log4cxx] std::exception from configure: " <<
ex.what() << std::endl;
return 11;
} catch (...) {
std::cerr << "[sample_log4cxx] Unknown exception from configure" <<
std::endl;
return 12;
}
Stage("DOMConfigurator::configure() returned");
LoggerPtr root = Logger::getRootLogger();
Stage("Emitting test logs");
LOG4CXX_INFO(root, "sample info");
LOG4CXX_WARN(root, "sample warn");
LOG4CXX_ERROR(root, "sample error");
Stage("Shutting down LogManager");
LogManager::shutdown();
Stage("Completed successfully");
return 0;
}<?xml version="1.0" encoding="UTF-8" ?>
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="SampleStartAppender" class="SampleDBAppender">
<param name="DBBRAND" value="POSTGRESQL"/>
<param name="SQL_POSTGRESQL" value="JUST TESTING 1 %d"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="JUST TESTING 1 %d"/>
</layout>
</appender>
<appender name="ASYNC" class="SampleASyncAppender">
<param name="BLOCKING" value="false"/>
<param name="BUFFERSIZE" value="256"/>
<param name="DSN" value="Oracle_postgre"/>
<param name="USER" value="vis_as_rep_t2"/>
<param name="PASSWORD" value="Passw0rd"/>
<param name="DBBRAND" value="POSTGRESQL"/>
<param name="SQL" value="SELECT INSTANCE_ID FROM LOG_INFO WHERE HOST_NAME = '[S_HOST]' AND REPOSITORY_PATH = '[S_REPOSITORY]' AND PORT_NUMBER = [S_PORT_NUMBER] AND S_START_DATE_TIME = TO_TIMESTAMP('[START_DATE_TIME]','yyyy/mm/dd HH24:MI:SS.MS')"/>
<appender-ref ref="SampleStartAppender"/>
</appender>
<root>
<priority value="all" />
<appender-ref ref="ASYNC"/>
</root>
</log4j:configuration>