From 97703870a72f60d7169e5d04d47cc2db5989bb17 Mon Sep 17 00:00:00 2001 From: Dominik Lohmann Date: Tue, 16 Jan 2024 19:23:53 +0100 Subject: [PATCH] Fix delivering response promises in actor state destructors --- libcaf_core/src/response_promise.cpp | 29 ++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/libcaf_core/src/response_promise.cpp b/libcaf_core/src/response_promise.cpp index 0a3b090ab2..c5b50309f5 100644 --- a/libcaf_core/src/response_promise.cpp +++ b/libcaf_core/src/response_promise.cpp @@ -166,22 +166,31 @@ void response_promise::state::cancel() { void response_promise::state::deliver_impl(message msg) { CAF_LOG_TRACE(CAF_ARG(msg)); - // Even though we are holding a weak pointer, we can access the pointer - // without any additional check here because only the actor itself is allowed - // to call this function. - auto self = static_cast(weak_self.get()->get()); + auto cancel_guard = detail::make_scope_guard([this] { + cancel(); + }); if (msg.empty() && id.is_async()) { CAF_LOG_DEBUG("drop response: empty response to asynchronous input"); - } else if (!stages.empty()) { + return; + } + auto self = weak_self.lock(); + if (self == nullptr) { + auto element = make_mailbox_element(self, id.response_id(), + std::move(stages), + std::move(msg)); + source->enqueue(std::move(element), nullptr); + return; + } + if (!stages.empty()) { auto next = std::move(stages.back()); stages.pop_back(); detail::profiled_send(self, std::move(source), next, id, std::move(stages), self->context(), std::move(msg)); - } else if (source != nullptr) { - detail::profiled_send(self, self->ctrl(), source, id.response_id(), - forwarding_stack{}, self->context(), std::move(msg)); - } - cancel(); + return; + } + CAF_ASSERT(source != nullptr); + detail::profiled_send(self, self->ctrl(), source, id.response_id(), + forwarding_stack{}, self->context(), std::move(msg)); } void response_promise::state::delegate_impl(abstract_actor* receiver,