From 80e6f6b6846faa70715d216d51b90a43754e4074 Mon Sep 17 00:00:00 2001 From: Nathan Brei Date: Tue, 16 Jun 2026 19:59:23 -0400 Subject: [PATCH 1/5] CMake: Use cppzmq instead of libzmq --- CMakeLists.txt | 4 ++-- cmake/FindZeroMQ.cmake | 34 ---------------------------------- cmake/JANAConfig.cmake.in | 2 +- cmake/MakeConfig.cmake | 2 -- 4 files changed, 3 insertions(+), 39 deletions(-) delete mode 100644 cmake/FindZeroMQ.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index d904d6db3..cd0083899 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -110,7 +110,7 @@ else() endif() if (${USE_ZEROMQ}) - find_package(ZeroMQ REQUIRED) + find_package(cppzmq REQUIRED) endif() if (${USE_XERCES}) @@ -192,7 +192,7 @@ else() message(STATUS "USE_ROOT Off") endif() if (${USE_ZEROMQ}) - message(STATUS "USE_ZEROMQ On") + message(STATUS "USE_ZEROMQ On --> " ${cppzmq_DIR}) else() message(STATUS "USE_ZEROMQ Off") endif() diff --git a/cmake/FindZeroMQ.cmake b/cmake/FindZeroMQ.cmake deleted file mode 100644 index c07c0f637..000000000 --- a/cmake/FindZeroMQ.cmake +++ /dev/null @@ -1,34 +0,0 @@ -set(PKG_CONFIG_USE_CMAKE_PREFIX_PATH ON) -find_package(PkgConfig) -pkg_check_modules(PC_LIBZMQ QUIET libzmq) - -set(ZeroMQ_VERSION ${PC_LIBZMQ_VERSION}) - -find_path(ZeroMQ_INCLUDE_DIR zmq.h - PATHS ${ZeroMQ_DIR}/include - ${PC_LIBZMQ_INCLUDE_DIRS}) - -find_library(ZeroMQ_LIBRARY - NAMES zmq - PATHS ${ZeroMQ_DIR}/lib - ${PC_LIBZMQ_LIBDIR} - ${PC_LIBZMQ_LIBRARY_DIRS}) - -if(ZeroMQ_LIBRARY) - set(ZeroMQ_FOUND ON) -endif() - -set ( ZeroMQ_LIBRARIES ${ZeroMQ_LIBRARY} ) -set ( ZeroMQ_INCLUDE_DIRS ${ZeroMQ_INCLUDE_DIR} ) - -if(NOT TARGET libzmq) - add_library(libzmq UNKNOWN IMPORTED) - set_target_properties(libzmq PROPERTIES - IMPORTED_LOCATION ${ZeroMQ_LIBRARIES} - INTERFACE_INCLUDE_DIRECTORIES ${ZeroMQ_INCLUDE_DIRS}) -endif() - -include ( FindPackageHandleStandardArgs ) -# handle the QUIETLY and REQUIRED arguments and set ZMQ_FOUND to TRUE -# if all listed variables are TRUE -find_package_handle_standard_args ( ZeroMQ DEFAULT_MSG ZeroMQ_LIBRARIES ZeroMQ_INCLUDE_DIRS ) \ No newline at end of file diff --git a/cmake/JANAConfig.cmake.in b/cmake/JANAConfig.cmake.in index a8b90869b..eac54cd3e 100644 --- a/cmake/JANAConfig.cmake.in +++ b/cmake/JANAConfig.cmake.in @@ -19,7 +19,7 @@ if(USE_ROOT) endif() set(USE_ZEROMQ @USE_ZEROMQ@) if(USE_ZEROMQ) - find_dependency(ZeroMQ REQUIRED) + find_dependency(cppzmq REQUIRED) endif() # Provide user with shared libraries by default if JANA was built with them. diff --git a/cmake/MakeConfig.cmake b/cmake/MakeConfig.cmake index fab15e685..aba0927c9 100644 --- a/cmake/MakeConfig.cmake +++ b/cmake/MakeConfig.cmake @@ -33,5 +33,3 @@ install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/cmake/AddJanaLibrary.cmake" install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/cmake/AddJanaTest.cmake" DESTINATION "lib/JANA/cmake") -install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/cmake/FindZeroMQ.cmake" - DESTINATION "lib/JANA/cmake") From 3f46917430de5067c523347cc58cbe76fb8c20bd Mon Sep 17 00:00:00 2001 From: Nathan Brei Date: Tue, 16 Jun 2026 20:31:24 -0400 Subject: [PATCH 2/5] Fix ubuntu platform test --- .github/workflows/test_platform_ubuntu.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test_platform_ubuntu.yml b/.github/workflows/test_platform_ubuntu.yml index c0b4a4d76..271e80578 100644 --- a/.github/workflows/test_platform_ubuntu.yml +++ b/.github/workflows/test_platform_ubuntu.yml @@ -12,7 +12,7 @@ jobs: strategy: matrix: #os: [ubuntu-20.04, ubuntu-22.04] - os: [ubuntu-22.04] + os: [ubuntu-24.04] # See https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobsjob_idruns-on for available platforms runs-on: ${{ matrix.os }} @@ -25,13 +25,12 @@ jobs: - name: deps run: | sudo apt-get update - sudo apt-get install -y libzmq3-dev libxerces-c-dev python3-dev + sudo apt-get install -y cppzmq-dev libxerces-c-dev python3-dev - name: cmake run: | mkdir -p $GITHUB_WORKSPACE/build cd $GITHUB_WORKSPACE/build cmake ../ -DCMAKE_INSTALL_PREFIX=$GITHUB_WORKSPACE/Linux \ - -DCMAKE_CXX_FLAGS="-Werror" \ -DCMAKE_CXX_STANDARD=20 \ -DUSE_PYTHON=ON \ -DUSE_ROOT=OFF \ From aca5d223c575df677d9839a0166ad43c7620e887 Mon Sep 17 00:00:00 2001 From: Nathan Brei Date: Tue, 16 Jun 2026 23:43:20 -0400 Subject: [PATCH 3/5] Fix dependency matrix tests --- .github/workflows/test_dependency_matrix.yml | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/.github/workflows/test_dependency_matrix.yml b/.github/workflows/test_dependency_matrix.yml index f108ce54d..a7f5eb4ad 100644 --- a/.github/workflows/test_dependency_matrix.yml +++ b/.github/workflows/test_dependency_matrix.yml @@ -16,6 +16,10 @@ jobs: - uses: actions/checkout@v4 - name: build run: | + # LD_LIBRARY_PATH needs to be set HERE in order to propagate to CTest now. (I don't like this!) + # CTest needs the LD_LIBRARY_PATH set so that ROOT can find the dictionaries for Podio IO. + # (Remember that ROOT won't use RPath for this purpose) + export LD_LIBRARY_PATH=/app/podio/install/lib:$LD_LIBRARY_PATH cmake -S . -B build \ -DCMAKE_INSTALL_PREFIX=`pwd` \ -DUSE_PYTHON=ON \ @@ -43,29 +47,21 @@ jobs: - name: JTest run: | - export LD_LIBRARY_PATH=/app/podio/install/lib:$LD_LIBRARY_PATH - # Note that podio needs to be on the LD_LIBRARY_PATH, not merely someone's RPath, because - # Cling needs to be able to find the libpodioDict* ctest --test-dir build --output-on-failure -R jana-plugin-jtest-tests - name: jana-unit-tests run: | - export LD_LIBRARY_PATH=/app/podio/install/lib:$LD_LIBRARY_PATH ctest --test-dir build --output-on-failure -R jana-unit-tests - name: TimesliceExample with simple (physics event) topology run: | - export LD_LIBRARY_PATH=/app/podio/install/lib:$LD_LIBRARY_PATH ctest --test-dir build --output-on-failure -R jana-example-timeslices-simple-tests - name: TimesliceExample with complex (timeslice) topology run: | - export LD_LIBRARY_PATH=/app/podio/install/lib:$LD_LIBRARY_PATH ctest --test-dir build --output-on-failure -R jana-example-timeslices-complex-tests - name: Janadot run: | - export LD_LIBRARY_PATH=/app/podio/install/lib:$LD_LIBRARY_PATH ctest --test-dir build --output-on-failure -R jana-plugin-janadot-tests - name: Other examples run: | - export LD_LIBRARY_PATH=/app/podio/install/lib:$LD_LIBRARY_PATH ctest --test-dir build --output-on-failure -R "jana-example-dst-tests|jana-example-tutorial-tests|jana-example-eventgroup-tests|jana-example-unit-tests|jana-example-podio-tests" From 62384a31a7b9939560e88f655c46f96ed9a06600 Mon Sep 17 00:00:00 2001 From: Nathan Brei Date: Wed, 27 May 2026 15:56:58 -0400 Subject: [PATCH 4/5] JLogger::Level accepts spdlog synonyms Also, JLogger::Level::FATAL now canonicalizes to "critical" to avoid wacky race conditions caused by different default values. This was inspired by an issue caused by the parameter names for the JANA2 logger service colliding with those used by ePIC's spdlog service. It's desirable for the same parameter to control both loggers, but we need a smoother on-ramp. This brings us into closer agreement with spdlog, which might eventually supplant the JLogger completely. --- src/libraries/JANA/JLogger.h | 2 +- src/libraries/JANA/Services/JParameterManager.h | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/libraries/JANA/JLogger.h b/src/libraries/JANA/JLogger.h index be1c77306..be5372966 100644 --- a/src/libraries/JANA/JLogger.h +++ b/src/libraries/JANA/JLogger.h @@ -57,7 +57,7 @@ inline std::ostream& operator<<(std::ostream& s, JLogger::Level l) { case JLogger::Level::INFO: return s << "info"; case JLogger::Level::WARN: return s << "warn"; case JLogger::Level::ERROR: return s << "error"; - case JLogger::Level::FATAL: return s << "fatal"; + case JLogger::Level::FATAL: return s << "critical"; default: return s << "off"; } } diff --git a/src/libraries/JANA/Services/JParameterManager.h b/src/libraries/JANA/Services/JParameterManager.h index 021000df0..6e96b273d 100644 --- a/src/libraries/JANA/Services/JParameterManager.h +++ b/src/libraries/JANA/Services/JParameterManager.h @@ -466,12 +466,21 @@ inline void JParameterManager::Parse(const std::string& in, JLogger::Level& out) else if (std::strcmp(token.c_str(), "warn") == 0) { out = JLogger::Level::WARN; } + else if (std::strcmp(token.c_str(), "warning") == 0) { + out = JLogger::Level::WARN; + } else if (std::strcmp(token.c_str(), "error") == 0) { out = JLogger::Level::ERROR; } + else if (std::strcmp(token.c_str(), "err") == 0) { + out = JLogger::Level::ERROR; + } else if (std::strcmp(token.c_str(), "fatal") == 0) { out = JLogger::Level::FATAL; } + else if (std::strcmp(token.c_str(), "critical") == 0) { + out = JLogger::Level::FATAL; + } else if (std::strcmp(token.c_str(), "off") == 0) { out = JLogger::Level::OFF; } From 651d62235413ff5529d26cae517e0bd24be573bf Mon Sep 17 00:00:00 2001 From: Nathan Brei Date: Wed, 17 Jun 2026 00:02:55 -0400 Subject: [PATCH 5/5] Improve logging of swallowed exceptions Addresses issue #496 --- src/libraries/JANA/JFactory.cc | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/libraries/JANA/JFactory.cc b/src/libraries/JANA/JFactory.cc index 372ca9f2b..0ef3208be 100644 --- a/src/libraries/JANA/JFactory.cc +++ b/src/libraries/JANA/JFactory.cc @@ -2,6 +2,8 @@ // Copyright 2023, Jefferson Science Associates, LLC. // Subject to the terms in the LICENSE file found in the top-level directory. +#include +#include #include #include #include @@ -240,13 +242,31 @@ void JFactory::Create(const JEvent& event) { throw JException("Invalid callback style"); } } + catch (JException& ex) { + // Save everything already created even if we throw an exception + // This is so that we leave everything in a valid state just in case someone tries to catch the exception recover, + // such as EICrecon. (Remember that a missing collection in the podio frame will segfault if anyone tries to write that frame) + // Note that the collections themselves won't know that they exited early + + LOG_DEBUG(GetLogger()) << "Exception in JFactory::Create, prefix=" << GetPrefix() + << ", message=" << ex.GetMessage(); + mStatus = Status::Excepted; + mException = std::current_exception(); + for (auto* output : GetOutputs()) { + output->LagrangianStore(*event.GetFactorySet(), JDatabundle::Status::Excepted); + } + for (auto* output : GetVariadicOutputs()) { + output->LagrangianStore(*event.GetFactorySet(), JDatabundle::Status::Excepted); + } + throw; + } catch (...) { // Save everything already created even if we throw an exception // This is so that we leave everything in a valid state just in case someone tries to catch the exception recover, // such as EICrecon. (Remember that a missing collection in the podio frame will segfault if anyone tries to write that frame) // Note that the collections themselves won't know that they exited early - LOG << "Exception in JFactory::Create, prefix=" << GetPrefix(); + LOG_DEBUG(GetLogger()) << "Exception in JFactory::Create, prefix=" << GetPrefix(); mStatus = Status::Excepted; mException = std::current_exception(); for (auto* output : GetOutputs()) {