diff options
author | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2021-07-01 22:15:54 +0300 |
---|---|---|
committer | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2021-07-11 17:41:59 +0300 |
commit | 1f7f7a72ed47a4a9cbfcda9dc26f490d5ef7b1af (patch) | |
tree | 6eaf5ade279b03c19f6ca0f7fc0b8a9eb447d765 /test | |
parent | 4c63bb4938b88bf8005c4f3dbe378c05ece70b3a (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>
Diffstat (limited to 'test')
-rw-r--r-- | test/message.cpp | 66 |
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; } |