Unverified Commit 27645ccb authored by Joseph Noir's avatar Joseph Noir Committed by GitHub

Merge pull request #1118

Capture message text of exceptions if actors die
parents 3ae46b22 4adb13e2
...@@ -54,6 +54,8 @@ is based on [Keep a Changelog](https://keepachangelog.com). ...@@ -54,6 +54,8 @@ is based on [Keep a Changelog](https://keepachangelog.com).
- The `to_string` output for `error` now renders the error code enum by default. - The `to_string` output for `error` now renders the error code enum by default.
This renders the member functions `actor_system::render` and This renders the member functions `actor_system::render` and
`actor_system_config::render` obsolete. `actor_system_config::render` obsolete.
- Actors that die due to an unhandled exception now use `sec::runtime_error`
consistently. This makes `exit_reason::unhandled_exception` obsolete.
### Changed ### Changed
......
...@@ -104,6 +104,8 @@ int main(int argc, char** argv) { ...@@ -104,6 +104,8 @@ int main(int argc, char** argv) {
<< "// DO NOT EDIT: " << "// DO NOT EDIT: "
"this file is auto-generated by caf-generate-enum-strings.\n" "this file is auto-generated by caf-generate-enum-strings.\n"
"// Run the target update-enum-strings if this file is out of sync.\n" "// Run the target update-enum-strings if this file is out of sync.\n"
"#include \"caf/config.hpp\"\n\n"
"CAF_PUSH_DEPRECATED_WARNING\n\n"
<< "#include \"" << namespaces[0]; << "#include \"" << namespaces[0];
for (size_t i = 1; i < namespaces.size(); ++i) for (size_t i = 1; i < namespaces.size(); ++i)
out << '/' << namespaces[i]; out << '/' << namespaces[i];
...@@ -142,4 +144,5 @@ int main(int argc, char** argv) { ...@@ -142,4 +144,5 @@ int main(int argc, char** argv) {
<< "}\n\n"; << "}\n\n";
for (auto i = namespaces.rbegin(); i != namespaces.rend(); ++i) for (auto i = namespaces.rbegin(); i != namespaces.rend(); ++i)
out << "} // namespace " << *i << '\n'; out << "} // namespace " << *i << '\n';
out << "\nCAF_POP_WARNINGS\n";
} }
...@@ -35,7 +35,7 @@ enum class exit_reason : uint8_t { ...@@ -35,7 +35,7 @@ enum class exit_reason : uint8_t {
/// Indicates that an actor finished execution without error. /// Indicates that an actor finished execution without error.
normal = 0, normal = 0,
/// Indicates that an actor died because of an unhandled exception. /// Indicates that an actor died because of an unhandled exception.
unhandled_exception, unhandled_exception [[deprecated("superseded by sec::runtime_error")]],
/// Indicates that the exit reason for this actor is unknown, i.e., /// Indicates that the exit reason for this actor is unknown, i.e.,
/// the actor has been terminated and no longer exists. /// the actor has been terminated and no longer exists.
unknown, unknown,
......
...@@ -250,7 +250,8 @@ public: ...@@ -250,7 +250,8 @@ public:
static void default_exit_handler(pointer ptr, exit_msg& x); static void default_exit_handler(pointer ptr, exit_msg& x);
#ifdef CAF_ENABLE_EXCEPTIONS #ifdef CAF_ENABLE_EXCEPTIONS
static error default_exception_handler(pointer ptr, std::exception_ptr& x); static error default_exception_handler(local_actor* ptr,
std::exception_ptr& x);
#endif // CAF_ENABLE_EXCEPTIONS #endif // CAF_ENABLE_EXCEPTIONS
// -- constructors and destructors ------------------------------------------- // -- constructors and destructors -------------------------------------------
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include "caf/detail/sync_request_bouncer.hpp" #include "caf/detail/sync_request_bouncer.hpp"
#include "caf/invoke_message_result.hpp" #include "caf/invoke_message_result.hpp"
#include "caf/logger.hpp" #include "caf/logger.hpp"
#include "caf/scheduled_actor.hpp"
#include "caf/telemetry/timer.hpp" #include "caf/telemetry/timer.hpp"
namespace caf { namespace caf {
...@@ -121,7 +122,8 @@ void blocking_actor::launch(execution_unit*, bool, bool hide) { ...@@ -121,7 +122,8 @@ void blocking_actor::launch(execution_unit*, bool, bool hide) {
self->act(); self->act();
rsn = self->fail_state_; rsn = self->fail_state_;
} catch (...) { } catch (...) {
rsn = exit_reason::unhandled_exception; auto ptr = std::current_exception();
rsn = scheduled_actor::default_exception_handler(self, ptr);
} }
try { try {
self->on_exit(); self->on_exit();
......
// clang-format off // clang-format off
// DO NOT EDIT: this file is auto-generated by caf-generate-enum-strings. // DO NOT EDIT: this file is auto-generated by caf-generate-enum-strings.
// Run the target update-enum-strings if this file is out of sync. // Run the target update-enum-strings if this file is out of sync.
#include "caf/config.hpp"
CAF_PUSH_DEPRECATED_WARNING
#include "caf/exit_reason.hpp" #include "caf/exit_reason.hpp"
#include <string> #include <string>
...@@ -31,3 +35,5 @@ std::string to_string(exit_reason x) { ...@@ -31,3 +35,5 @@ std::string to_string(exit_reason x) {
} }
} // namespace caf } // namespace caf
CAF_POP_WARNINGS
// clang-format off // clang-format off
// DO NOT EDIT: this file is auto-generated by caf-generate-enum-strings. // DO NOT EDIT: this file is auto-generated by caf-generate-enum-strings.
// Run the target update-enum-strings if this file is out of sync. // Run the target update-enum-strings if this file is out of sync.
#include "caf/config.hpp"
CAF_PUSH_DEPRECATED_WARNING
#include "caf/intrusive/inbox_result.hpp" #include "caf/intrusive/inbox_result.hpp"
#include <string> #include <string>
...@@ -23,3 +27,5 @@ std::string to_string(inbox_result x) { ...@@ -23,3 +27,5 @@ std::string to_string(inbox_result x) {
} // namespace intrusive } // namespace intrusive
} // namespace caf } // namespace caf
CAF_POP_WARNINGS
// clang-format off // clang-format off
// DO NOT EDIT: this file is auto-generated by caf-generate-enum-strings. // DO NOT EDIT: this file is auto-generated by caf-generate-enum-strings.
// Run the target update-enum-strings if this file is out of sync. // Run the target update-enum-strings if this file is out of sync.
#include "caf/config.hpp"
CAF_PUSH_DEPRECATED_WARNING
#include "caf/intrusive/task_result.hpp" #include "caf/intrusive/task_result.hpp"
#include <string> #include <string>
...@@ -25,3 +29,5 @@ std::string to_string(task_result x) { ...@@ -25,3 +29,5 @@ std::string to_string(task_result x) {
} // namespace intrusive } // namespace intrusive
} // namespace caf } // namespace caf
CAF_POP_WARNINGS
// clang-format off // clang-format off
// DO NOT EDIT: this file is auto-generated by caf-generate-enum-strings. // DO NOT EDIT: this file is auto-generated by caf-generate-enum-strings.
// Run the target update-enum-strings if this file is out of sync. // Run the target update-enum-strings if this file is out of sync.
#include "caf/config.hpp"
CAF_PUSH_DEPRECATED_WARNING
#include "caf/invoke_message_result.hpp" #include "caf/invoke_message_result.hpp"
#include <string> #include <string>
...@@ -21,3 +25,5 @@ std::string to_string(invoke_message_result x) { ...@@ -21,3 +25,5 @@ std::string to_string(invoke_message_result x) {
} }
} // namespace caf } // namespace caf
CAF_POP_WARNINGS
// clang-format off // clang-format off
// DO NOT EDIT: this file is auto-generated by caf-generate-enum-strings. // DO NOT EDIT: this file is auto-generated by caf-generate-enum-strings.
// Run the target update-enum-strings if this file is out of sync. // Run the target update-enum-strings if this file is out of sync.
#include "caf/config.hpp"
CAF_PUSH_DEPRECATED_WARNING
#include "caf/message_priority.hpp" #include "caf/message_priority.hpp"
#include <string> #include <string>
...@@ -19,3 +23,5 @@ std::string to_string(message_priority x) { ...@@ -19,3 +23,5 @@ std::string to_string(message_priority x) {
} }
} // namespace caf } // namespace caf
CAF_POP_WARNINGS
// clang-format off // clang-format off
// DO NOT EDIT: this file is auto-generated by caf-generate-enum-strings. // DO NOT EDIT: this file is auto-generated by caf-generate-enum-strings.
// Run the target update-enum-strings if this file is out of sync. // Run the target update-enum-strings if this file is out of sync.
#include "caf/config.hpp"
CAF_PUSH_DEPRECATED_WARNING
#include "caf/pec.hpp" #include "caf/pec.hpp"
#include <string> #include <string>
...@@ -61,3 +65,5 @@ std::string to_string(pec x) { ...@@ -61,3 +65,5 @@ std::string to_string(pec x) {
} }
} // namespace caf } // namespace caf
CAF_POP_WARNINGS
...@@ -96,22 +96,24 @@ void scheduled_actor::default_exit_handler(scheduled_actor* ptr, exit_msg& x) { ...@@ -96,22 +96,24 @@ void scheduled_actor::default_exit_handler(scheduled_actor* ptr, exit_msg& x) {
} }
#ifdef CAF_ENABLE_EXCEPTIONS #ifdef CAF_ENABLE_EXCEPTIONS
error scheduled_actor::default_exception_handler(pointer ptr, error scheduled_actor::default_exception_handler(local_actor* ptr,
std::exception_ptr& x) { std::exception_ptr& x) {
CAF_ASSERT(x != nullptr); CAF_ASSERT(x != nullptr);
try { try {
std::rethrow_exception(x); std::rethrow_exception(x);
} catch (const std::exception& e) { } catch (std::exception& e) {
auto pretty_type = detail::pretty_type_name(typeid(e));
aout(ptr) << "*** unhandled exception: [id: " << ptr->id() aout(ptr) << "*** unhandled exception: [id: " << ptr->id()
<< ", name: " << ptr->name() << ", name: " << ptr->name()
<< ", exception typeid: " << typeid(e).name() << "]: " << e.what() << ", exception typeid: " << pretty_type << "]: " << e.what()
<< std::endl; << std::endl;
return make_error(sec::runtime_error, std::move(pretty_type), e.what());
} catch (...) { } catch (...) {
aout(ptr) << "*** unhandled exception: [id: " << ptr->id() aout(ptr) << "*** unhandled exception: [id: " << ptr->id()
<< ", name: " << ptr->name() << "]: unknown exception" << ", name: " << ptr->name() << "]: unknown exception"
<< std::endl; << std::endl;
}
return sec::runtime_error; return sec::runtime_error;
}
} }
#endif // CAF_ENABLE_EXCEPTIONS #endif // CAF_ENABLE_EXCEPTIONS
......
// clang-format off // clang-format off
// DO NOT EDIT: this file is auto-generated by caf-generate-enum-strings. // DO NOT EDIT: this file is auto-generated by caf-generate-enum-strings.
// Run the target update-enum-strings if this file is out of sync. // Run the target update-enum-strings if this file is out of sync.
#include "caf/config.hpp"
CAF_PUSH_DEPRECATED_WARNING
#include "caf/sec.hpp" #include "caf/sec.hpp"
#include <string> #include <string>
...@@ -125,3 +129,5 @@ std::string to_string(sec x) { ...@@ -125,3 +129,5 @@ std::string to_string(sec x) {
} }
} // namespace caf } // namespace caf
CAF_POP_WARNINGS
// clang-format off // clang-format off
// DO NOT EDIT: this file is auto-generated by caf-generate-enum-strings. // DO NOT EDIT: this file is auto-generated by caf-generate-enum-strings.
// Run the target update-enum-strings if this file is out of sync. // Run the target update-enum-strings if this file is out of sync.
#include "caf/config.hpp"
CAF_PUSH_DEPRECATED_WARNING
#include "caf/stream_priority.hpp" #include "caf/stream_priority.hpp"
#include <string> #include <string>
...@@ -25,3 +29,5 @@ std::string to_string(stream_priority x) { ...@@ -25,3 +29,5 @@ std::string to_string(stream_priority x) {
} }
} // namespace caf } // namespace caf
CAF_POP_WARNINGS
...@@ -28,21 +28,24 @@ using namespace caf; ...@@ -28,21 +28,24 @@ using namespace caf;
# error "building unit test for exception handlers in no-exceptions build" # error "building unit test for exception handlers in no-exceptions build"
#endif #endif
behavior testee() {
return {
[](const std::string&) { throw std::runtime_error("whatever"); },
};
}
class exception_testee : public event_based_actor { class exception_testee : public event_based_actor {
public: public:
~exception_testee() override;
exception_testee(actor_config& cfg) : event_based_actor(cfg) { exception_testee(actor_config& cfg) : event_based_actor(cfg) {
set_exception_handler([](std::exception_ptr&) -> error { set_exception_handler([](std::exception_ptr&) -> error {
return exit_reason::remote_link_unreachable; return exit_reason::remote_link_unreachable;
}); });
} }
~exception_testee() override;
behavior make_behavior() override { behavior make_behavior() override {
return { return testee();
[](const std::string&) {
throw std::runtime_error("whatever");
}
};
} }
}; };
...@@ -50,7 +53,26 @@ exception_testee::~exception_testee() { ...@@ -50,7 +53,26 @@ exception_testee::~exception_testee() {
// avoid weak-vtables warning // avoid weak-vtables warning
} }
CAF_TEST(test_custom_exception_handler) { CAF_TEST(the default exception handler includes the error message) {
using std::string;
actor_system_config cfg;
actor_system system{cfg};
scoped_actor self{system};
auto aut = self->spawn(testee);
self->request(aut, infinite, "hello world")
.receive( //
[] { CAF_FAIL("unexpected response"); },
[](const error& err) {
auto msg = err.context();
if (auto view = make_typed_message_view<string, string>(msg)) {
CAF_CHECK_EQUAL(get<1>(view), "whatever");
} else {
CAF_FAIL("unexpected error contest: " << err.context());
}
});
}
CAF_TEST(actors can override the default exception handler) {
actor_system_config cfg; actor_system_config cfg;
actor_system system{cfg}; actor_system system{cfg};
auto handler = [](std::exception_ptr& eptr) -> error { auto handler = [](std::exception_ptr& eptr) -> error {
...@@ -63,7 +85,7 @@ CAF_TEST(test_custom_exception_handler) { ...@@ -63,7 +85,7 @@ CAF_TEST(test_custom_exception_handler) {
catch (...) { catch (...) {
// "fall through" // "fall through"
} }
return exit_reason::unhandled_exception; return sec::runtime_error;
}; };
scoped_actor self{system}; scoped_actor self{system};
auto testee1 = self->spawn<monitored>([=](event_based_actor* eb_self) { auto testee1 = self->spawn<monitored>([=](event_based_actor* eb_self) {
......
// clang-format off // clang-format off
// DO NOT EDIT: this file is auto-generated by caf-generate-enum-strings. // DO NOT EDIT: this file is auto-generated by caf-generate-enum-strings.
// Run the target update-enum-strings if this file is out of sync. // Run the target update-enum-strings if this file is out of sync.
#include "caf/config.hpp"
CAF_PUSH_DEPRECATED_WARNING
#include "caf/io/basp/message_type.hpp" #include "caf/io/basp/message_type.hpp"
#include <string> #include <string>
...@@ -33,3 +37,5 @@ std::string to_string(message_type x) { ...@@ -33,3 +37,5 @@ std::string to_string(message_type x) {
} // namespace basp } // namespace basp
} // namespace io } // namespace io
} // namespace caf } // namespace caf
CAF_POP_WARNINGS
// clang-format off // clang-format off
// DO NOT EDIT: this file is auto-generated by caf-generate-enum-strings. // DO NOT EDIT: this file is auto-generated by caf-generate-enum-strings.
// Run the target update-enum-strings if this file is out of sync. // Run the target update-enum-strings if this file is out of sync.
#include "caf/config.hpp"
CAF_PUSH_DEPRECATED_WARNING
#include "caf/io/network/operation.hpp" #include "caf/io/network/operation.hpp"
#include <string> #include <string>
...@@ -25,3 +29,5 @@ std::string to_string(operation x) { ...@@ -25,3 +29,5 @@ std::string to_string(operation x) {
} // namespace network } // namespace network
} // namespace io } // namespace io
} // namespace caf } // namespace caf
CAF_POP_WARNINGS
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment