From b353f45fed45846a213d2f2b60a6936295b17c87 Mon Sep 17 00:00:00 2001 From: Ivo van Dongen Date: Thu, 25 May 2017 15:19:14 +0300 Subject: [core] add test to demonstrate waiting threads in mailbox::receive won't crash on self-closing --- test/actor/actor.test.cpp | 56 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/test/actor/actor.test.cpp b/test/actor/actor.test.cpp index 638c24ed7d..3d97469628 100644 --- a/test/actor/actor.test.cpp +++ b/test/actor/actor.test.cpp @@ -155,6 +155,62 @@ TEST(Actor, DestructionAllowedInReceiveOnSameThread) { ASSERT_EQ(std::future_status::ready, status); } +TEST(Actor, SelfDestructionDoesntCrashWaitingReceivingThreads) { + // Ensures destruction doesn't cause waiting threads to + // crash when a actor closes it's own mailbox from a + // callback + + struct Test { + + Test(ActorRef){}; + + void callMeBack(std::function callback) { + callback(); + } + }; + + + ThreadPool pool { 2 }; + + std::promise actorClosedPromise; + + auto closingActor = std::make_unique>(pool); + auto waitingActor = std::make_unique>(pool); + + std::atomic waitingMessageProcessed {false}; + + // Callback (triggered while mutex is locked in Mailbox::receive()) + closingActor->invoke(&Test::callMeBack, [&]() { + + // Queue up another message from another thread + std::promise messageQueuedPromise; + waitingActor->invoke(&Test::callMeBack, [&]() { + // This will be waiting on the mutex in + // Mailbox::receive(), holding a lock + // on the weak_ptr so the mailbox is not + // destroyed + closingActor->invoke(&Test::callMeBack, [&]() { + waitingMessageProcessed.store(true); + }); + messageQueuedPromise.set_value(); + }); + + // Wait for the message to be queued + ASSERT_EQ( + messageQueuedPromise.get_future().wait_for(std::chrono::seconds(1)), + std::future_status::ready + ); + + // Destroy the Actor/Mailbox in the same thread + closingActor.reset(); + actorClosedPromise.set_value(); + }); + + auto status = actorClosedPromise.get_future().wait_for(std::chrono::seconds(1)); + ASSERT_EQ(std::future_status::ready, status); + ASSERT_FALSE(waitingMessageProcessed.load()); +} + TEST(Actor, OrderedMailbox) { // Messages are processed in order. -- cgit v1.2.1