diff options
author | Ivo van Dongen <info@ivovandongen.nl> | 2017-05-25 15:19:14 +0300 |
---|---|---|
committer | Ivo van Dongen <ivovandongen@users.noreply.github.com> | 2017-05-27 09:25:03 +0300 |
commit | b353f45fed45846a213d2f2b60a6936295b17c87 (patch) | |
tree | 25bb53ddb78353dd42a971abcb7c75acf8a31856 | |
parent | b608d85db78cb672da76cb4531438ba32843c6fb (diff) | |
download | qtlocation-mapboxgl-b353f45fed45846a213d2f2b60a6936295b17c87.tar.gz |
[core] add test to demonstrate waiting threads in mailbox::receive won't crash on self-closing
-rw-r--r-- | test/actor/actor.test.cpp | 56 |
1 files changed, 56 insertions, 0 deletions
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<Test>){}; + + void callMeBack(std::function<void ()> callback) { + callback(); + } + }; + + + ThreadPool pool { 2 }; + + std::promise<void> actorClosedPromise; + + auto closingActor = std::make_unique<Actor<Test>>(pool); + auto waitingActor = std::make_unique<Actor<Test>>(pool); + + std::atomic<bool> waitingMessageProcessed {false}; + + // Callback (triggered while mutex is locked in Mailbox::receive()) + closingActor->invoke(&Test::callMeBack, [&]() { + + // Queue up another message from another thread + std::promise<void> 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. |