From 6767b3bb09d185a11acb465cb9fe59e366c49e75 Mon Sep 17 00:00:00 2001 From: Sichao25 Date: Wed, 17 Dec 2025 14:55:55 -0500 Subject: [PATCH 1/2] create error handling logic --- src/pcms/assert.cpp | 44 +++++++++++++++++++++++++++++++++ src/pcms/assert.h | 48 ++++++++++++++++++++++++++++++++++++ test/CMakeLists.txt | 1 + test/test_error_handling.cpp | 20 +++++++++++++++ 4 files changed, 113 insertions(+) create mode 100644 test/test_error_handling.cpp diff --git a/src/pcms/assert.cpp b/src/pcms/assert.cpp index abd3e449..adea747c 100644 --- a/src/pcms/assert.cpp +++ b/src/pcms/assert.cpp @@ -4,6 +4,50 @@ #include namespace pcms { + +namespace +{ +error_mode current_mode = error_mode::throw_exception; +} + +void set_error_mode(error_mode mode) +{ + current_mode = mode; +} + +void handle_error(const exception& e) +{ + switch (current_mode) { + case error_mode::throw_exception: throw e; + + case error_mode::abort: std::abort(); + + case error_mode::return_code: + default: break; + } +} + +void handle_mpi_error(const pcms::exception& e) +{ + int local_fatal = (e.level() == pcms::error_level::fatal); + int global_fatal = 0; + + MPI_Allreduce(&local_fatal, &global_fatal, 1, MPI_INT, MPI_MAX, + MPI_COMM_WORLD); + + switch (current_mode) { + case pcms::error_mode::throw_exception: throw e; + + case pcms::error_mode::abort: + if (global_fatal) + MPI_Abort(MPI_COMM_WORLD, e.code()); + break; + + case pcms::error_mode::return_code: + default: break; + } +} + void Pcms_Assert_Fail(const char* msg) { printError("%s", msg); diff --git a/src/pcms/assert.h b/src/pcms/assert.h index 8565aec9..52f04e6e 100644 --- a/src/pcms/assert.h +++ b/src/pcms/assert.h @@ -1,6 +1,9 @@ #ifndef PCMS_COUPLING_ASSERT_H #define PCMS_COUPLING_ASSERT_H #include +#include +#include +#include #include // https://stackoverflow.com/questions/16683146/can-macros-be-overloaded-by-number-of-arguments @@ -44,6 +47,51 @@ namespace pcms { +enum class error_level +{ + recoverable, // safe to continue + resource_leak, // may cause resource leaks + fatal // undefined or broken state +}; + +enum class error_mode +{ + return_code, + throw_exception, + abort +}; + +class exception : public std::exception +{ +public: + exception(std::string message, int error_code = 0, + error_level level = error_level::fatal, std::string specific = {}) + : error_code_(error_code), level_(level) + { + std::ostringstream oss; + oss << message; + if (!specific.empty()) + oss << " | Details: " << specific; + if (error_code_ != 0) + oss << " | Error code: " << error_code_; + error_message_ = oss.str(); + } + + const char* what() const noexcept override { return error_message_.c_str(); } + + int code() const noexcept { return error_code_; } + error_level level() const noexcept { return level_; } + +private: + std::string error_message_; + int error_code_; + error_level level_; +}; + +void set_error_mode(error_mode mode); +void handle_error(const exception& e); +void handle_mpi_error(const exception& e); + // from scorec/core/pcu_fail.h void Pcms_Assert_Fail(const char* msg) __attribute__((noreturn)); } // namespace pcms diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 4325dab2..d320d70f 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -382,6 +382,7 @@ if(Catch2_FOUND) list( APPEND PCMS_UNIT_TEST_SOURCES + test_error_handling.cpp test_field_transfer.cpp test_uniform_grid.cpp test_omega_h_copy.cpp diff --git a/test/test_error_handling.cpp b/test/test_error_handling.cpp new file mode 100644 index 00000000..240a26e3 --- /dev/null +++ b/test/test_error_handling.cpp @@ -0,0 +1,20 @@ +#include +#include "pcms/assert.h" +#include "pcms/print.h" +#include + +int raise_error(int code) +{ + if (code) { + pcms::handle_error(pcms::exception("Mesh validation failed", 1, + pcms::error_level::recoverable)); + + return 1; + } + return 0; +} + +TEST_CASE("pcms error handling test") +{ + REQUIRE_THROWS_AS(raise_error(1), pcms::exception); +} \ No newline at end of file From 2aa42c4911b85ee414858b3f0135712ccf454e35 Mon Sep 17 00:00:00 2001 From: Sichao25 Date: Tue, 23 Dec 2025 19:59:13 -0500 Subject: [PATCH 2/2] remove error handler --- src/pcms/assert.cpp | 44 ------------------------------------ src/pcms/assert.h | 24 ++------------------ test/test_error_handling.cpp | 4 +--- 3 files changed, 3 insertions(+), 69 deletions(-) diff --git a/src/pcms/assert.cpp b/src/pcms/assert.cpp index adea747c..abd3e449 100644 --- a/src/pcms/assert.cpp +++ b/src/pcms/assert.cpp @@ -4,50 +4,6 @@ #include namespace pcms { - -namespace -{ -error_mode current_mode = error_mode::throw_exception; -} - -void set_error_mode(error_mode mode) -{ - current_mode = mode; -} - -void handle_error(const exception& e) -{ - switch (current_mode) { - case error_mode::throw_exception: throw e; - - case error_mode::abort: std::abort(); - - case error_mode::return_code: - default: break; - } -} - -void handle_mpi_error(const pcms::exception& e) -{ - int local_fatal = (e.level() == pcms::error_level::fatal); - int global_fatal = 0; - - MPI_Allreduce(&local_fatal, &global_fatal, 1, MPI_INT, MPI_MAX, - MPI_COMM_WORLD); - - switch (current_mode) { - case pcms::error_mode::throw_exception: throw e; - - case pcms::error_mode::abort: - if (global_fatal) - MPI_Abort(MPI_COMM_WORLD, e.code()); - break; - - case pcms::error_mode::return_code: - default: break; - } -} - void Pcms_Assert_Fail(const char* msg) { printError("%s", msg); diff --git a/src/pcms/assert.h b/src/pcms/assert.h index 52f04e6e..70624e67 100644 --- a/src/pcms/assert.h +++ b/src/pcms/assert.h @@ -47,26 +47,12 @@ namespace pcms { -enum class error_level -{ - recoverable, // safe to continue - resource_leak, // may cause resource leaks - fatal // undefined or broken state -}; - -enum class error_mode -{ - return_code, - throw_exception, - abort -}; class exception : public std::exception { public: - exception(std::string message, int error_code = 0, - error_level level = error_level::fatal, std::string specific = {}) - : error_code_(error_code), level_(level) + exception(std::string message, int error_code = 0, std::string specific = {}) + : error_code_(error_code) { std::ostringstream oss; oss << message; @@ -80,18 +66,12 @@ class exception : public std::exception const char* what() const noexcept override { return error_message_.c_str(); } int code() const noexcept { return error_code_; } - error_level level() const noexcept { return level_; } private: std::string error_message_; int error_code_; - error_level level_; }; -void set_error_mode(error_mode mode); -void handle_error(const exception& e); -void handle_mpi_error(const exception& e); - // from scorec/core/pcu_fail.h void Pcms_Assert_Fail(const char* msg) __attribute__((noreturn)); } // namespace pcms diff --git a/test/test_error_handling.cpp b/test/test_error_handling.cpp index 240a26e3..d2b9764b 100644 --- a/test/test_error_handling.cpp +++ b/test/test_error_handling.cpp @@ -6,9 +6,7 @@ int raise_error(int code) { if (code) { - pcms::handle_error(pcms::exception("Mesh validation failed", 1, - pcms::error_level::recoverable)); - + throw pcms::exception("Test exception", code, "Raising error for testing"); return 1; } return 0;