summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>2021-07-01 22:15:54 +0300
committerLaurent Pinchart <laurent.pinchart@ideasonboard.com>2021-07-11 17:41:59 +0300
commit1f7f7a72ed47a4a9cbfcda9dc26f490d5ef7b1af (patch)
tree6eaf5ade279b03c19f6ca0f7fc0b8a9eb447d765
parent4c63bb4938b88bf8005c4f3dbe378c05ece70b3a (diff)
test: message: Test recursive Thread::dispatchMessages() calls
The Thread::dispatchMessages() function needs to support recursive calls, for instance to allow flushing delivery of invoked methods. Add a corresponding test, which currently fails with a double free. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Jacopo Mondi <jacopo@jmondi.org> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
-rw-r--r--test/message.cpp66
1 files changed, 64 insertions, 2 deletions
diff --git a/test/message.cpp b/test/message.cpp
index eeea57fe..d148a13d 100644
--- a/test/message.cpp
+++ b/test/message.cpp
@@ -7,6 +7,7 @@
#include <chrono>
#include <iostream>
+#include <memory>
#include <thread>
#include <libcamera/base/message.h>
@@ -26,8 +27,8 @@ public:
MessageReceived,
};
- MessageReceiver()
- : status_(NoMessage)
+ MessageReceiver(Object *parent = nullptr)
+ : Object(parent), status_(NoMessage)
{
}
@@ -52,6 +53,45 @@ private:
Status status_;
};
+class RecursiveMessageReceiver : public Object
+{
+public:
+ RecursiveMessageReceiver()
+ : child_(this), success_(false)
+ {
+ }
+
+ bool success() const { return success_; }
+
+protected:
+ void message([[maybe_unused]] Message *msg)
+ {
+ if (msg->type() != Message::None) {
+ Object::message(msg);
+ return;
+ }
+
+ child_.postMessage(std::make_unique<Message>(Message::None));
+
+ /*
+ * If the child has already received the message, something is
+ * wrong.
+ */
+ if (child_.status() != MessageReceiver::NoMessage)
+ return;
+
+ Thread::current()->dispatchMessages(Message::None);
+
+ /* The child should now have received the message. */
+ if (child_.status() == MessageReceiver::MessageReceived)
+ success_ = true;
+ }
+
+private:
+ MessageReceiver child_;
+ bool success_;
+};
+
class SlowMessageReceiver : public Object
{
protected:
@@ -120,6 +160,28 @@ protected:
delete slowReceiver;
+ this_thread::sleep_for(chrono::milliseconds(100));
+
+ /*
+ * Test recursive calls to Thread::dispatchMessages(). Messages
+ * should be delivered correctly, without crashes or memory
+ * leaks. Two messages need to be posted to ensure we don't only
+ * test the simple case of a queue containing a single message.
+ */
+ std::unique_ptr<RecursiveMessageReceiver> recursiveReceiver =
+ std::make_unique<RecursiveMessageReceiver>();
+ recursiveReceiver->moveToThread(&thread_);
+
+ recursiveReceiver->postMessage(std::make_unique<Message>(Message::None));
+ recursiveReceiver->postMessage(std::make_unique<Message>(Message::UserMessage));
+
+ this_thread::sleep_for(chrono::milliseconds(10));
+
+ if (!recursiveReceiver->success()) {
+ cout << "Recursive message delivery failed" << endl;
+ return TestFail;
+ }
+
return TestPass;
}