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>

Reply via email to