Skip to content

Commit

Permalink
JException displays wrapped exception type
Browse files Browse the repository at this point in the history
Addresses issue #277.
  • Loading branch information
nathanwbrei committed May 3, 2024
1 parent 10754a4 commit 2fe9303
Show file tree
Hide file tree
Showing 7 changed files with 79 additions and 3 deletions.
8 changes: 7 additions & 1 deletion src/libraries/JANA/JException.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,12 @@ struct JException : public std::exception {
/// Convenience method for formatting complete error data
inline friend std::ostream& operator<<(std::ostream& os, JException const& ex) {
os << "JException" << std::endl;
os << " Message: " << ex.message << std::endl;
if (ex.exception_type.length() != 0) {
os << " Type: " << ex.exception_type << std::endl;
}
if (ex.message.length() != 0) {
os << " Message: " << ex.message << std::endl;
}
if (ex.function_name.length() != 0) {
os << " Function: " << ex.function_name << std::endl;
}
Expand All @@ -65,6 +70,7 @@ struct JException : public std::exception {
return os;
}

std::string exception_type;
std::string message;
std::string plugin_name;
std::string type_name;
Expand Down
7 changes: 7 additions & 0 deletions src/libraries/JANA/JFactory.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include <JANA/JFactory.h>
#include <JANA/JEvent.h>
#include <JANA/Utils/JTypeInfo.h>


void JFactory::Create(const std::shared_ptr<const JEvent>& event) {
Expand All @@ -27,6 +28,7 @@ void JFactory::Create(const std::shared_ptr<const JEvent>& event) {
}
catch (std::exception& e) {
auto ex = JException("Exception in JFactoryT::Init(): %s", e.what());
ex.exception_type = JTypeInfo::demangle_current_exception_type();
ex.nested_exception = std::current_exception();
ex.function_name = "JFactory::Init";
ex.type_name = mFactoryName;
Expand All @@ -36,6 +38,7 @@ void JFactory::Create(const std::shared_ptr<const JEvent>& event) {
}
catch (...) {
auto ex = JException("Unknown exception");
ex.exception_type = JTypeInfo::demangle_current_exception_type();
ex.nested_exception = std::current_exception();
ex.function_name = "JFactory::Init";
ex.type_name = mFactoryName;
Expand Down Expand Up @@ -76,6 +79,7 @@ void JFactory::Create(const std::shared_ptr<const JEvent>& event) {
}
catch (std::exception& e) {
auto ex = JException(e.what());
ex.exception_type = JTypeInfo::demangle_current_exception_type();
ex.nested_exception = std::current_exception();
ex.function_name = "JFactory::BeginRun/ChangeRun/EndRun";
ex.type_name = mFactoryName;
Expand All @@ -85,6 +89,7 @@ void JFactory::Create(const std::shared_ptr<const JEvent>& event) {
}
catch (...) {
auto ex = JException("Unknown exception");
ex.exception_type = JTypeInfo::demangle_current_exception_type();
ex.nested_exception = std::current_exception();
ex.function_name = "JFactory::BeginRun/ChangeRun/EndRun";
ex.type_name = mFactoryName;
Expand All @@ -105,6 +110,7 @@ void JFactory::Create(const std::shared_ptr<const JEvent>& event) {
}
catch (std::exception& e) {
auto ex = JException(e.what());
ex.exception_type = JTypeInfo::demangle_current_exception_type();
ex.nested_exception = std::current_exception();
ex.function_name = "JFactory::Process";
ex.type_name = mFactoryName;
Expand All @@ -114,6 +120,7 @@ void JFactory::Create(const std::shared_ptr<const JEvent>& event) {
}
catch (...) {
auto ex = JException("Unknown exception");
ex.exception_type = JTypeInfo::demangle_current_exception_type();
ex.nested_exception = std::current_exception();
ex.function_name = "JFactory::Process";
ex.type_name = mFactoryName;
Expand Down
3 changes: 3 additions & 0 deletions src/libraries/JANA/Omni/JComponent.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#pragma once
#include <JANA/JApplication.h>
#include <JANA/Omni/JComponentFwd.h>
#include <JANA/Utils/JTypeInfo.h>

namespace jana {
namespace omni {
Expand Down Expand Up @@ -126,6 +127,7 @@ inline void JComponent::CallWithJExceptionWrapper(std::string func_name, F func)
}
catch (std::exception& e) {
auto ex = JException(e.what());
ex.exception_type = JTypeInfo::demangle_current_exception_type();
ex.nested_exception = std::current_exception();
ex.function_name = func_name;
ex.type_name = m_type_name;
Expand All @@ -135,6 +137,7 @@ inline void JComponent::CallWithJExceptionWrapper(std::string func_name, F func)
}
catch (...) {
auto ex = JException("Unknown exception");
ex.exception_type = JTypeInfo::demangle_current_exception_type();
ex.nested_exception = std::current_exception();
ex.function_name = func_name;
ex.type_name = m_type_name;
Expand Down
1 change: 1 addition & 0 deletions src/libraries/JANA/Utils/JAutoActivator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

JAutoActivator::JAutoActivator() {
SetTypeName("JAutoActivator");
SetCallbackStyle(CallbackStyle::ExpertMode);
}

void JAutoActivator::AddAutoActivatedFactory(string factory_name, string factory_tag) {
Expand Down
14 changes: 12 additions & 2 deletions src/libraries/JANA/Utils/JTypeInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,11 @@ struct is_serializable<T, std::void_t<decltype(std::declval<std::ostream>() << s


template<typename T>
std::string demangle(void) {
std::string demangle() {

/// Return the demangled name (if available) for the type the template
/// is based. Call it like this:
/// cout << GetDemangledName<MyType>() << endl;
/// cout << demangle<MyType>() << endl;
int status = -1;
auto cstr = abi::__cxa_demangle(typeid(T).name(), NULL, NULL, &status);
std::string type(cstr);
Expand All @@ -41,6 +41,16 @@ std::string demangle(void) {
}


inline std::string demangle_current_exception_type() {

int status = -1;
auto cstr = abi::__cxa_demangle(abi::__cxa_current_exception_type()->name(), NULL, NULL, &status);
std::string type(cstr);
free(cstr);
if (status != 0) type = abi::__cxa_current_exception_type()->name();
return type;
}

/// Macro for conveniently turning a variable name into a string. This is used by JObject::Summarize
/// in order to play nicely with refactoring tools. Because the symbol is picked up by the
/// preprocessor and not the compiler, no demangling is necessary.
Expand Down
23 changes: 23 additions & 0 deletions src/programs/unit_tests/Components/JEventProcessorTests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,26 @@ TEST_CASE("JEventProcessor_ExpertMode_ProcessCount") {
REQUIRE(destroy_count == 1);
}

struct MyExceptingProcessor : public JEventProcessor {
void Process(const std::shared_ptr<const JEvent>&) override {
throw std::runtime_error("Mystery!");
}
};

TEST_CASE("JEventProcessor_Exception") {
JApplication app;
app.Add(new JEventSource);
app.Add(new MyExceptingProcessor);
bool found_throw = false;
try {
app.Run();
}
catch(JException& ex) {
REQUIRE(ex.function_name == "JEventProcessor::Process");
REQUIRE(ex.message == "Mystery!");
REQUIRE(ex.exception_type == "std::runtime_error");
found_throw = true;
}
REQUIRE(found_throw == true);

}
26 changes: 26 additions & 0 deletions src/programs/unit_tests/Components/JFactoryTests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -221,3 +221,29 @@ TEST_CASE("JFactoryTests") {
}
}


struct MyExceptingFactory : public JFactoryT<JFactoryTestDummyObject> {
void Process(const std::shared_ptr<const JEvent>&) override {
throw std::runtime_error("Weird mystery!");
}
};

TEST_CASE("JFactory_Exception") {
JApplication app;
app.Add(new JEventSource);
app.Add(new JFactoryGeneratorT<MyExceptingFactory>());
app.SetParameterValue("autoactivate", "JFactoryTestDummyObject");
bool found_throw = false;
try {
app.Run();
}
catch(JException& ex) {
LOG << ex << LOG_END;
REQUIRE(ex.function_name == "JFactory::Process");
REQUIRE(ex.message == "Weird mystery!");
REQUIRE(ex.exception_type == "std::runtime_error");
found_throw = true;
}
REQUIRE(found_throw == true);
}

0 comments on commit 2fe9303

Please sign in to comment.