diff --git a/tdactor/td/actor/impl/ActorInfo.h b/tdactor/td/actor/impl/ActorInfo.h index 5a4cc1e3..9654cbb2 100644 --- a/tdactor/td/actor/impl/ActorInfo.h +++ b/tdactor/td/actor/impl/ActorInfo.h @@ -70,14 +70,13 @@ inline void ActorInfo::on_actor_moved(Actor *actor_new_ptr) { inline void ActorInfo::clear() { // LOG_IF(WARNING, !mailbox_.empty()) << "Destroy actor with non-empty mailbox: " << get_name() // << format::as_array(mailbox_); - mailbox_.clear(); + CHECK(mailbox_.empty()); + CHECK(!actor_); CHECK(!is_running()); CHECK(!is_migrating()); // NB: must be in non migrating state // store invalid scheduler id. sched_id_.store((1 << 30) - 1, std::memory_order_relaxed); - destroy_actor(); - // Destroy context only after destructor. context_.reset(); } @@ -93,6 +92,7 @@ inline void ActorInfo::destroy_actor() { break; } actor_ = nullptr; + mailbox_.clear(); } template diff --git a/tdactor/td/actor/impl/Scheduler.cpp b/tdactor/td/actor/impl/Scheduler.cpp index 26367444..b84c5722 100644 --- a/tdactor/td/actor/impl/Scheduler.cpp +++ b/tdactor/td/actor/impl/Scheduler.cpp @@ -369,6 +369,7 @@ void Scheduler::do_stop_actor(ActorInfo *actor_info) { event_context_ptr_->flags = 0; } else { owner_ptr = actor_info->get_actor_unsafe()->clear(); + actor_info->destroy_actor(); } destroy_actor(actor_info); } diff --git a/tdactor/test/actors_main.cpp b/tdactor/test/actors_main.cpp index 31f93247..1ccec2b3 100644 --- a/tdactor/test/actors_main.cpp +++ b/tdactor/test/actors_main.cpp @@ -465,3 +465,55 @@ TEST(Actors, do_after_stop) { } sched.finish(); } + +class XContext : public ActorContext { + public: + void validate() { + CHECK(x == 1234); + } + ~XContext() { + x = 0; + } + int x = 1234; +}; +class WithContext : public Actor { + public: + void start_up() override { + set_context(std::make_shared()); + } + void f(unique_ptr guard) { + } + void close() { + stop(); + } + + private: +}; + +void check_context() { + auto ptr = static_cast(Scheduler::context()); + CHECK(ptr); + ptr->validate(); +} + +TEST(Actors, context_during_destruction) { + SET_VERBOSITY_LEVEL(VERBOSITY_NAME(ERROR)); + + ConcurrentScheduler sched; + int threads_n = 0; + sched.init(threads_n); + + { + auto guard = sched.get_main_guard(); + auto with_context = create_actor("WithContext").release(); + send_closure(with_context, &WithContext::f, create_lambda_guard([] { check_context(); })); + send_closure_later(with_context, &WithContext::close); + send_closure(with_context, &WithContext::f, create_lambda_guard([] { check_context(); })); + send_closure(with_context, &WithContext::f, create_lambda_guard([] { Scheduler::instance()->finish(); })); + } + sched.start(); + while (sched.run_main(10)) { + // empty + } + sched.finish(); +} diff --git a/test/data.cpp b/test/data.cpp index 67cfe20c..f6143da1 100644 --- a/test/data.cpp +++ b/test/data.cpp @@ -4,7 +4,7 @@ // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // -#include "test/data.h" +#include "data.h" namespace td { static const char thumbnail_arr[] = "_9j_4AAQSkZJRgABAQEASABIAAD_2wBDAAICAgICAQICAgIDAgIDAwYEAwMDAwcFBQQGCAcJCAgHCAgJCg0LCQoMCggICw8LDA0ODg8OCQsQERAOEQ" diff --git a/test/http.cpp b/test/http.cpp index 463d4aa0..8268ee64 100644 --- a/test/http.cpp +++ b/test/http.cpp @@ -33,7 +33,7 @@ #include "td/utils/Status.h" #include "td/utils/UInt.h" -#include "test/data.h" +#include "data.h" #include #include