Unverified Commit b3164d5b authored by Noir's avatar Noir Committed by GitHub

Merge pull request #1379

Provide better diagnostic for missing meta objects
parents 26b0a900 00f7bb3a
......@@ -21,6 +21,9 @@ is based on [Keep a Changelog](https://keepachangelog.com).
single objects.
- Typed actors that use the type-erased pointer-view type received access to the
new flow API functions (e.g., `make_observable`).
- Not initializing the meta objects table now prints a diagnosis message before
aborting the program. Previously, the application would usually just crash due
to a `nullptr`-access inside some CAF function.
### Fixed
......
......@@ -179,7 +179,7 @@ public:
}
error abort_reason() const {
impl_->abort_reason();
return impl_->abort_reason();
}
private:
......
......@@ -64,8 +64,13 @@ CAF_CORE_EXPORT global_meta_objects_guard_type global_meta_objects_guard();
/// is the index for accessing the corresponding meta object.
CAF_CORE_EXPORT span<const meta_object> global_meta_objects();
/// Returns the global meta object for given type ID.
CAF_CORE_EXPORT const meta_object* global_meta_object(type_id_t id);
/// Returns the global meta object for given type ID. Aborts the program if no
/// meta object exists for `id`.
CAF_CORE_EXPORT const meta_object& global_meta_object(type_id_t id);
/// Returns the global meta object for given type ID or `nullptr` if no meta
/// object exists for `id`.
CAF_CORE_EXPORT const meta_object* global_meta_object_or_null(type_id_t id);
/// Clears the array for storing global meta objects.
/// @warning intended for unit testing only!
......
......@@ -35,17 +35,17 @@ bool batch::data::save(Inspector& sink) const {
sink.emplace_error(sec::unsafe_type);
return false;
}
auto meta = detail::global_meta_object(item_type_);
auto& meta = detail::global_meta_object(item_type_);
auto ptr = storage_;
if (!sink.begin_sequence(size_))
return false;
auto len = size_;
do {
if constexpr (std::is_same_v<Inspector, binary_serializer>) {
if (!meta->save_binary(sink, ptr))
if (!meta.save_binary(sink, ptr))
return false;
} else {
if (!meta->save(sink, ptr))
if (!meta.save(sink, ptr))
return false;
}
ptr += item_size_;
......
......@@ -194,12 +194,12 @@ error_code<sec> config_value::default_construct(type_id_t id) {
set(uri{});
return sec::none;
default:
if (auto meta = detail::global_meta_object(id)) {
if (auto meta = detail::global_meta_object_or_null(id)) {
using detail::make_scope_guard;
auto ptr = malloc(meta->padded_size);
auto free_guard = detail::make_scope_guard([ptr] { free(ptr); });
auto free_guard = make_scope_guard([ptr] { free(ptr); });
meta->default_construct(ptr);
auto destroy_guard
= detail::make_scope_guard([=] { meta->destroy(ptr); });
auto destroy_guard = make_scope_guard([=] { meta->destroy(ptr); });
config_value_writer writer{this};
if (meta->save(writer, ptr)) {
return sec::none;
......@@ -519,13 +519,12 @@ config_value::parse_msg_impl(std::string_view str,
return false;
auto pos = ptr->storage();
for (auto type : ls) {
auto meta = detail::global_meta_object(type);
CAF_ASSERT(meta != nullptr);
meta->default_construct(pos);
auto& meta = detail::global_meta_object(type);
meta.default_construct(pos);
ptr->inc_constructed_elements();
if (!meta->load(reader, pos))
if (!meta.load(reader, pos))
return false;
pos += meta->padded_size;
pos += meta.padded_size;
}
result.reset(ptr.release(), false);
return reader.end_sequence();
......
......@@ -51,10 +51,28 @@ span<const meta_object> global_meta_objects() {
return {meta_objects, meta_objects_size};
}
const meta_object* global_meta_object(type_id_t id) {
const meta_object& global_meta_object(type_id_t id) {
if (id < meta_objects_size) {
auto& meta = meta_objects[id];
return !meta.type_name.empty() ? &meta : nullptr;
if (!meta.type_name.empty())
return meta;
}
CAF_CRITICAL_FMT(
"found no meta object for type ID %d!\n"
" This usually means that run-time type initialization is missing.\n"
" With CAF_MAIN, make sure to pass all custom type ID blocks.\n"
" With a custom main, call (before any other CAF function):\n"
" - caf::core::init_global_meta_objects()\n"
" - <module>::init_global_meta_objects() for all loaded modules\n"
" - caf::init_global_meta_objects<T>() for all custom ID blocks",
static_cast<int>(id));
}
const meta_object* global_meta_object_or_null(type_id_t id) {
if (id < meta_objects_size) {
auto& meta = meta_objects[id];
if (!meta.type_name.empty())
return &meta;
}
return nullptr;
}
......
......@@ -64,21 +64,19 @@ int error::compare(uint8_t code, type_id_t category) const noexcept {
// -- inspection support -----------------------------------------------------
std::string to_string(const error& x) {
using const_void_ptr = const void*;
using const_meta_ptr = const detail::meta_object*;
if (!x)
return "none";
std::string result;
auto append = [&result](const_void_ptr ptr,
const_meta_ptr meta) -> const_void_ptr {
meta->stringify(result, ptr);
return static_cast<const std::byte*>(ptr) + meta->padded_size;
auto append = [&result](const void* ptr,
const detail::meta_object& meta) -> const void* {
meta.stringify(result, ptr);
return static_cast<const std::byte*>(ptr) + meta.padded_size;
};
auto code = x.code();
append(&code, detail::global_meta_object(x.category()));
if (auto& ctx = x.context()) {
result += '(';
auto ptr = static_cast<const_void_ptr>(ctx.cdata().storage());
auto ptr = static_cast<const void*>(ctx.cdata().storage());
auto types = ctx.types();
ptr = append(ptr, detail::global_meta_object(types[0]));
for (size_t index = 1; index < types.size(); ++index) {
......
......@@ -71,8 +71,8 @@ bool load_data(Deserializer& source, message::data_ptr& data) {
CAF_ASSERT(ids.size() == msg_size);
size_t data_size = 0;
for (auto id : ids) {
if (auto meta_obj = detail::global_meta_object(id))
data_size += meta_obj->padded_size;
if (auto meta = detail::global_meta_object_or_null(id))
data_size += meta->padded_size;
else
STOP(sec::unknown_type);
}
......@@ -155,7 +155,7 @@ bool load_data(Deserializer& source, message::data_ptr& data) {
for (size_t i = 0; i < msg_size; ++i) {
auto type = type_id_t{0};
GUARDED(source.fetch_next_object_type(type));
if (auto meta_obj = detail::global_meta_object(type)) {
if (auto meta_obj = detail::global_meta_object_or_null(type)) {
ids.push_back(type);
auto obj_size = meta_obj->padded_size;
data_size += obj_size;
......@@ -289,14 +289,12 @@ std::string to_string(const message& msg) {
auto types = msg.types();
if (!types.empty()) {
auto ptr = msg.cdata().storage();
auto meta = detail::global_meta_object(types[0]);
CAF_ASSERT(meta != nullptr);
auto* meta = &detail::global_meta_object(types[0]);
meta->stringify(result, ptr);
ptr += meta->padded_size;
for (size_t index = 1; index < types.size(); ++index) {
result += ", ";
meta = detail::global_meta_object(types[index]);
CAF_ASSERT(meta != nullptr);
meta = &detail::global_meta_object(types[index]);
meta->stringify(result, ptr);
ptr += meta->padded_size;
}
......
......@@ -52,9 +52,9 @@ public:
}
std::byte* copy_init(std::byte* storage) const override {
auto* meta = global_meta_object(src_.type_at(index_));
meta->copy_construct(storage, src_.data().at(index_));
return storage + meta->padded_size;
auto& meta = global_meta_object(src_.type_at(index_));
meta.copy_construct(storage, src_.data().at(index_));
return storage + meta.padded_size;
}
std::byte* move_init(std::byte* storage) override {
......@@ -75,8 +75,8 @@ message_builder& message_builder::append_from(const caf::message& msg,
auto end = std::min(msg.size(), first + n);
for (size_t index = first; index < end; ++index) {
auto tid = msg.type_at(index);
auto* meta = detail::global_meta_object(tid);
storage_size_ += meta->padded_size;
auto& meta = detail::global_meta_object(tid);
storage_size_ += meta.padded_size;
types_.push_back(tid);
elements_.emplace_back(
std::make_unique<message_builder_element_adapter>(msg, index));
......
......@@ -9,8 +9,8 @@
namespace caf {
std::string_view query_type_name(type_id_t type) {
if (auto ptr = detail::global_meta_object(type))
return ptr->type_name;
if (auto meta = detail::global_meta_object_or_null(type))
return meta->type_name;
return {};
}
......
......@@ -12,10 +12,8 @@ namespace caf {
size_t type_id_list::data_size() const noexcept {
auto result = size_t{0};
for (auto type : *this) {
auto meta_obj = detail::global_meta_object(type);
result += meta_obj->padded_size;
}
for (auto type : *this)
result += detail::global_meta_object(type).padded_size;
return result;
}
......@@ -25,12 +23,12 @@ std::string to_string(type_id_list xs) {
std::string result;
result += '[';
{
auto tn = detail::global_meta_object(xs[0])->type_name;
auto tn = detail::global_meta_object(xs[0]).type_name;
result.insert(result.end(), tn.begin(), tn.end());
}
for (size_t index = 1; index < xs.size(); ++index) {
result += ", ";
auto tn = detail::global_meta_object(xs[index])->type_name;
auto tn = detail::global_meta_object(xs[index]).type_name;
result.insert(result.end(), tn.begin(), tn.end());
}
result += ']';
......
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