-
Notifications
You must be signed in to change notification settings - Fork 128
Description
General: I build Log4cxx from sources in macOS with LOG4CXX_MULTIPROCESS_ROLLING_FILE_APPENDER=on
with all dependencies linked statically in order to avoid adding any dylib (DSO) dependencies, because it will be used in a plug-in running in an environment I have little control over.
Set-up:
- MacMini M1, 2020; macOS Sequoia 15.5, Xcode 16.2 with its Command Line Tools;
- iMac x86_64, 2017, macOS Ventura 13.7, Xcode 15.2 with its Command Line Tools.
Build and run:
Get all necessary sources (including the recent patch):
get-src-log4cxx.sh
#!/usr/bin/env bash
curl -LOR https://github.com/libexpat/libexpat/releases/download/R_2_7_1/expat-2.7.1.tar.xz
tar -xf expat-2.7.1.tar.xz
curl -LOR https://dlcdn.apache.org/apr/apr-1.7.6.tar.bz2
tar -xf apr-1.7.6.tar.bz2
curl -LOR https://dlcdn.apache.org/apr/apr-iconv-1.2.2.tar.bz2
tar -xf apr-iconv-1.2.2.tar.bz2
curl -LOR https://dlcdn.apache.org/apr/apr-util-1.6.3.tar.bz2
tar -xf apr-util-1.6.3.tar.bz2
curl -LOR https://dlcdn.apache.org/logging/log4cxx/1.4.0/apache-log4cxx-1.4.0.tar.gz
tar -xf apache-log4cxx-1.4.0.tar.gz
pushd apache-log4cxx-1.4.0/src/test/cpp/rolling/
curl -LOR --ssl-no-revoke https://raw.githubusercontent.com/apache/logging-log4cxx/refs/heads/master/src/test/cpp/rolling/multiprocessrollingtest.cpp
popd
chmod -R go-w .
Build Log4cxx and run its tests:
build-log4cxx.sh
#!/usr/bin/env bash
set -o errexit
BUILD_DIR=$(dirname "$(readlink -f "$BASH_SOURCE")")
INSTALL_DIR=${BUILD_DIR}/Release
mkdir -p "${INSTALL_DIR}"
cmake -S expat-2.7.1 -B .gen/expat -DCMAKE_INSTALL_PREFIX="${INSTALL_DIR}" -DEXPAT_SHARED_LIBS=OFF
cmake --build .gen/expat --target install --config Release
pushd apr-1.7.6
./configure --prefix="${INSTALL_DIR}"
make -sj
make -s install
popd
#{ No need to build apr-iconv separately
#pushd apr-iconv-1.2.2
#./configure --prefix="${INSTALL_DIR}" --with-apr="${INSTALL_DIR}"
#make -sj
#make -s install
#popd
#}
pushd apr-util-1.6.3
./configure --prefix="${INSTALL_DIR}" --with-apr="${INSTALL_DIR}" --with-apr-iconv="../apr-iconv-1.2.2" --with-iconv=no
make -sj
make -s install
popd
cmake -S apache-log4cxx-1.4.0 -B .gen/log4cxx \
-DCMAKE_INSTALL_PREFIX="${INSTALL_DIR}" -DCMAKE_PREFIX_PATH="${INSTALL_DIR}" -DBUILD_SHARED_LIBS=off \
-DAPR_STATIC=yes -DAPU_STATIC=yes -DBUILD_SITE=OFF -DLOG4CXX_MULTIPROCESS_ROLLING_FILE_APPENDER=ON
cmake --build .gen/log4cxx --target install --config Release --parallel
ctest --test-dir .gen/log4cxx -C Release --output-on-failure
Input the test program:
hang.cpp
#include <log4cxx/defaultconfigurator.h>
#include <log4cxx/logger.h>
#include <log4cxx/logmanager.h>
int main() {
log4cxx::DefaultConfigurator::configure( log4cxx::LogManager::getLoggerRepository() );
LOG4CXX_WARN( log4cxx::Logger::getRootLogger(), "Exiting");
return 0;
}
and the configuration file:
log4cxx.xml
<log4j:configuration xmlns:log4j='http://logging.apache.org/'>
<appender name='RollingFiles' class='org.apache.log4j.rolling.MultiprocessRollingFileAppender'>
<rollingPolicy class='org.apache.log4j.rolling.TimeBasedRollingPolicy'>
<param name='FileNamePattern' value="%d{yyyy}.log"/>
<!-- Contrary to docs, the ActiveFileName option does not seem to be supported -->
</rollingPolicy>
<layout class='org.apache.log4j.PatternLayout'>
<param name='ConversionPattern' value="%m%n"/>
</layout>
</appender>
<appender name='Asynchronous' class='org.apache.log4j.AsyncAppender'>
<appender-ref ref='RollingFiles'/>
</appender>
<root>
<appender-ref ref='Asynchronous'/>
</root>
</log4j:configuration>
Build and run the test:
build-n-run.sh
clang -std=c++17 -O3 -DNDEBUG -lc++ -I"Release/include" -I"Release/include/apr-1" \
"Release/lib/liblog4cxx.a" "Release/lib/libaprutil-1.a" "Release/lib/libapr-1.a" "Release/lib/libexpat.a" \
-o hang -- hang.cpp
for n in {0..999} ; do echo $n && ./hang 2>/dev/null ; done
Expected: all test runs finish without freezes or crashes.
Actual: the very first test run hangs (both on arm64 and on x86_64).
Thread call stacks captured by Xcode on arm64 are:
Main thread
Thread 1 Queue : com.apple.main-thread (serial)
#0 0x000000018d20a9b8 in __ulock_wait ()
#1 0x000000018d24d0b0 in _pthread_join ()
#2 0x000000018d17ce84 in std::__1::thread::join ()
#3 0x0000000102dde8f0 in log4cxx::AsyncAppender::AsyncAppenderPriv::stopDispatcher ()
#4 0x0000000102dde7b4 in log4cxx::AsyncAppender::close ()
#5 0x0000000102dd2234 in log4cxx::helpers::AppenderAttachableImpl::removeAllAppenders ()
#6 0x0000000102e4683c in log4cxx::Logger::removeAllAppenders ()
#7 0x0000000102e22818 in log4cxx::Hierarchy::~Hierarchy ()
#8 0x0000000102e228a8 in log4cxx::Hierarchy::~Hierarchy ()
#9 0x0000000102e22904 in log4cxx::Hierarchy::~Hierarchy ()
#10 0x0000000102dd0c38 in std::__1::default_delete<log4cxx::AppenderSkeleton::AppenderSkeletonPrivate>::operator()[abi:ne180100] ()
#11 0x0000000102e2b67c in std::__1::__shared_ptr_pointer<log4cxx::Hierarchy*, std::__1::shared_ptr<log4cxx::Hierarchy>::__shared_ptr_default_delete<log4cxx::Hierarchy, log4cxx::Hierarchy>, std::__1::allocator<log4cxx::Hierarchy>>::__on_zero_shared ()
#12 0x0000000102dd5ee8 in std::__1::__shared_count::__release_shared[abi:ne180100] ()
#13 0x0000000102dd5e88 in std::__1::__shared_weak_count::__release_shared[abi:ne180100] ()
#14 0x0000000102dd5e58 in std::__1::shared_ptr<log4cxx::Level>::~shared_ptr[abi:ne180100] ()
#15 0x0000000102dd19fc in std::__1::shared_ptr<log4cxx::spi::Filter>::~shared_ptr[abi:ne180100] ()
#16 0x0000000102e0422c in log4cxx::spi::DefaultRepositorySelector::DefaultRepositorySelectorPrivate::~DefaultRepositorySelectorPrivate ()
#17 0x0000000102e04200 in log4cxx::spi::DefaultRepositorySelector::DefaultRepositorySelectorPrivate::~DefaultRepositorySelectorPrivate ()
#18 0x0000000102e041cc in std::__1::default_delete<log4cxx::spi::DefaultRepositorySelector::DefaultRepositorySelectorPrivate>::operator()[abi:ne180100] ()
#19 0x0000000102e04188 in std::__1::unique_ptr<log4cxx::spi::DefaultRepositorySelector::DefaultRepositorySelectorPrivate, std::__1::default_delete<log4cxx::spi::DefaultRepositorySelector::DefaultRepositorySelectorPrivate>>::reset[abi:ne180100] ()
#20 0x0000000102e04110 in std::__1::unique_ptr<log4cxx::spi::DefaultRepositorySelector::DefaultRepositorySelectorPrivate, std::__1::default_delete<log4cxx::spi::DefaultRepositorySelector::DefaultRepositorySelectorPrivate>>::~unique_ptr[abi:ne180100] ()
#21 0x0000000102e03f5c in std::__1::unique_ptr<log4cxx::spi::DefaultRepositorySelector::DefaultRepositorySelectorPrivate, std::__1::default_delete<log4cxx::spi::DefaultRepositorySelector::DefaultRepositorySelectorPrivate>>::~unique_ptr[abi:ne180100] ()
#22 0x0000000102e03f30 in log4cxx::spi::DefaultRepositorySelector::~DefaultRepositorySelector ()
#23 0x0000000102e03f94 in log4cxx::spi::DefaultRepositorySelector::~DefaultRepositorySelector ()
#24 0x0000000102dd83a0 in std::__1::__destroy_at[abi:ne180100]<log4cxx::spi::LoggingEvent, 0> ()
#25 0x0000000102e51614 in std::__1::allocator_traits<std::__1::allocator<log4cxx::spi::DefaultRepositorySelector>>::destroy[abi:ne180100]<log4cxx::spi::DefaultRepositorySelector, void, void> ()
#26 0x0000000102e515e4 in std::__1::__shared_ptr_emplace<log4cxx::spi::DefaultRepositorySelector, std::__1::allocator<log4cxx::spi::DefaultRepositorySelector>>::__on_zero_shared_impl[abi:ne180100]<std::__1::allocator<log4cxx::spi::DefaultRepositorySelector>, 0> ()
#27 0x0000000102e51464 in std::__1::__shared_ptr_emplace<log4cxx::spi::DefaultRepositorySelector, std::__1::allocator<log4cxx::spi::DefaultRepositorySelector>>::__on_zero_shared ()
#28 0x0000000102dd5ee8 in std::__1::__shared_count::__release_shared[abi:ne180100] ()
#29 0x0000000102dd5e88 in std::__1::__shared_weak_count::__release_shared[abi:ne180100] ()
#30 0x0000000102dd5e58 in std::__1::shared_ptr<log4cxx::Level>::~shared_ptr[abi:ne180100] ()
#31 0x0000000102dd19fc in std::__1::shared_ptr<log4cxx::spi::Filter>::~shared_ptr[abi:ne180100] ()
#32 0x0000000102dda8a8 in std::__1::pair<unsigned long, std::__1::shared_ptr<log4cxx::helpers::Object>>::~pair ()
#33 0x0000000102dda878 in std::__1::pair<unsigned long, std::__1::shared_ptr<log4cxx::helpers::Object>>::~pair ()
#34 0x0000000102dda850 in std::__1::__destroy_at[abi:ne180100]<std::__1::pair<unsigned long, std::__1::shared_ptr<log4cxx::helpers::Object>>, 0> ()
#35 0x0000000102dda7d8 in std::__1::allocator_traits<std::__1::allocator<std::__1::pair<unsigned long, std::__1::shared_ptr<log4cxx::helpers::Object>>>>::destroy[abi:ne180100]<std::__1::pair<unsigned long, std::__1::shared_ptr<log4cxx::helpers::Object>>, void, void> ()
#36 0x0000000102ddb498 in std::__1::vector<std::__1::pair<unsigned long, std::__1::shared_ptr<log4cxx::helpers::Object>>, std::__1::allocator<std::__1::pair<unsigned long, std::__1::shared_ptr<log4cxx::helpers::Object>>>>::__base_destruct_at_end[abi:ne180100] ()
#37 0x0000000102ddb418 in std::__1::vector<std::__1::pair<unsigned long, std::__1::shared_ptr<log4cxx::helpers::Object>>, std::__1::allocator<std::__1::pair<unsigned long, std::__1::shared_ptr<log4cxx::helpers::Object>>>>::__destruct_at_end[abi:ne180100] ()
#38 0x0000000102ddb380 in std::__1::vector<std::__1::pair<unsigned long, std::__1::shared_ptr<log4cxx::helpers::Object>>, std::__1::allocator<std::__1::pair<unsigned long, std::__1::shared_ptr<log4cxx::helpers::Object>>>>::pop_back ()
#39 0x0000000102ddb320 in log4cxx::helpers::APRInitializer::APRInitializerPrivate::~APRInitializerPrivate ()
#40 0x0000000102ddb2d0 in log4cxx::helpers::APRInitializer::APRInitializerPrivate::~APRInitializerPrivate ()
#41 0x0000000102ddb29c in std::__1::default_delete<log4cxx::helpers::APRInitializer::APRInitializerPrivate>::operator()[abi:ne180100] ()
#42 0x0000000102ddb258 in std::__1::unique_ptr<log4cxx::helpers::APRInitializer::APRInitializerPrivate, std::__1::default_delete<log4cxx::helpers::APRInitializer::APRInitializerPrivate>>::reset[abi:ne180100] ()
#43 0x0000000102ddb1e0 in std::__1::unique_ptr<log4cxx::helpers::APRInitializer::APRInitializerPrivate, std::__1::default_delete<log4cxx::helpers::APRInitializer::APRInitializerPrivate>>::~unique_ptr[abi:ne180100] ()
#44 0x0000000102dd8a08 in std::__1::unique_ptr<log4cxx::helpers::APRInitializer::APRInitializerPrivate, std::__1::default_delete<log4cxx::helpers::APRInitializer::APRInitializerPrivate>>::~unique_ptr[abi:ne180100] ()
#45 0x0000000102dd8aac in log4cxx::helpers::APRInitializer::~APRInitializer ()
#46 0x0000000102dd8be0 in log4cxx::helpers::APRInitializer::~APRInitializer ()
#47 0x0000000102ddb9dc in log4cxx::helpers::WideLife<log4cxx::helpers::APRInitializer>::~WideLife ()
#48 0x0000000102dd8eb0 in log4cxx::helpers::WideLife<log4cxx::helpers::APRInitializer>::~WideLife ()
#49 0x000000018d102944 in __cxa_finalize_ranges ()
#50 0x000000018d102704 in exit ()
#51 0x000000018d254dc8 in dyld4::LibSystemHelpers::exit ()
#52 0x000000018ceaacac in dyld4::LibSystemHelpersWrapper::exit ()
#53 0x000000018ceaabc8 in start ()
Worker thread
Thread 2
#0 0x0000000102dd8f2c in log4cxx::helpers::APRInitializer::getRootPool ()
#1 0x0000000102e78f80 in log4cxx::helpers::Pool::setPool ()
#2 0x0000000102e79040 in log4cxx::helpers::Pool::getAPRPool ()
#3 0x0000000102ed1890 in log4cxx::rolling::MultiprocessRollingFileAppender::isAlreadyRolled ()
#4 0x0000000102ed1e20 in log4cxx::rolling::MultiprocessRollingFileAppender::synchronizedRollover ()
#5 0x0000000102ed2bcc in log4cxx::rolling::MultiprocessRollingFileAppender::subAppend ()
#6 0x0000000102eb0348 in log4cxx::WriterAppender::append ()
#7 0x0000000102dd6ba0 in log4cxx::AppenderSkeleton::doAppendImpl ()
#8 0x0000000102dd6924 in log4cxx::AppenderSkeleton::doAppend ()
#9 0x0000000102dd18f4 in log4cxx::helpers::AppenderAttachableImpl::appendLoopOnAppenders ()
#10 0x0000000102ddddc0 in log4cxx::AsyncAppender::dispatch ()
#11 0x0000000102de37b4 in std::__1::__invoke[abi:ne180100]<void (log4cxx::WriterAppender::WriterAppenderPriv::*&)(), log4cxx::FileAppender::FileAppenderPriv*&, void> ()
#12 0x0000000102de36f8 in std::__1::__thread_execute[abi:ne180100]<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct>>, void (log4cxx::net::TelnetAppender::*)(), log4cxx::net::TelnetAppender*, 2ul> ()
#13 0x0000000102de342c in std::__1::__thread_proxy[abi:ne180100]<std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct>>, void (log4cxx::AsyncAppender::*)(), log4cxx::AsyncAppender*>> ()
#14 0x000000018d24ac0c in _pthread_start ()
Instructions in the offending stack frame:
EXC_BAD_ACCESS (code=1, address=0x0)
hang`log4cxx::helpers::APRInitializer::getRootPool:
0x102dd8f1c <+0>: stp x29, x30, [sp, #-0x10]!
0x102dd8f20 <+4>: mov x29, sp
0x102dd8f24 <+8>: bl 0x102dd8cbc ; log4cxx::helpers::APRInitializer::getInstance()
0x102dd8f28 <+12>: bl 0x102dd0208 ; std::__1::unique_ptr<log4cxx::rolling::Action::ActionPrivate, std::__1::default_delete<log4cxx::rolling::Action::ActionPrivate>>::get[abi:ne180100]() const
-> 0x102dd8f2c <+16>: ldr x0, [x0]
0x102dd8f30 <+20>: ldp x29, x30, [sp], #0x10
0x102dd8f34 <+24>: ret
Note: on x86_64 the call stacks are the same (at the source code level) and the disassembly is equivalent.