summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIvo van Dongen <info@ivovandongen.nl>2017-05-25 15:19:14 +0300
committerIvo van Dongen <ivovandongen@users.noreply.github.com>2017-05-27 09:25:03 +0300
commitb353f45fed45846a213d2f2b60a6936295b17c87 (patch)
tree25bb53ddb78353dd42a971abcb7c75acf8a31856
parentb608d85db78cb672da76cb4531438ba32843c6fb (diff)
downloadqtlocation-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.cpp56
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.