summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>2022-10-04 02:42:28 +0300
committerLaurent Pinchart <laurent.pinchart@ideasonboard.com>2022-10-04 17:58:00 +0300
commit036d26d6677e0b8e6cf284c0801b267c5f81720e (patch)
tree84ccd3cd40a1af11c1e6e81f247a5b36f8537beb
parentca33225ceb4c7b414eb1a8579af14c2c06f1f4ea (diff)
test: threads: Test thread cleanup upon abnormal termination
If a thread ends abnormally (that is, without retuning normally from its run() function, for instance with a direct call to pthread_cancel()), thread cleanup should still be performed. Add a test to ensure this. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Umang Jain <umang.jain@ideasonboard.com>
-rw-r--r--test/threads.cpp47
1 files changed, 47 insertions, 0 deletions
diff --git a/test/threads.cpp b/test/threads.cpp
index d83b5833..8f366c9d 100644
--- a/test/threads.cpp
+++ b/test/threads.cpp
@@ -8,7 +8,9 @@
#include <chrono>
#include <iostream>
#include <memory>
+#include <pthread.h>
#include <thread>
+#include <time.h>
#include <libcamera/base/thread.h>
@@ -35,6 +37,35 @@ private:
chrono::steady_clock::duration duration_;
};
+class CancelThread : public Thread
+{
+public:
+ CancelThread(bool &cancelled)
+ : cancelled_(cancelled)
+ {
+ }
+
+protected:
+ void run()
+ {
+ cancelled_ = true;
+
+ /*
+ * Cancel the thread and call a guaranteed cancellation point
+ * (nanosleep).
+ */
+ pthread_cancel(pthread_self());
+
+ struct timespec req{ 0, 100*000*000 };
+ nanosleep(&req, nullptr);
+
+ cancelled_ = false;
+ }
+
+private:
+ bool &cancelled_;
+};
+
class ThreadTest : public Test
{
protected:
@@ -118,6 +149,22 @@ protected:
return TestFail;
}
+ /* Test thread cleanup upon abnormal termination. */
+ bool cancelled = false;
+ bool finished = false;
+
+ thread = std::make_unique<CancelThread>(cancelled);
+ thread->finished.connect(this, [&finished]() { finished = true; });
+
+ thread->start();
+ thread->exit(0);
+ thread->wait(chrono::milliseconds(1000));
+
+ if (!cancelled || !finished) {
+ cout << "Cleanup failed upon abnormal termination" << endl;
+ return TestFail;
+ }
+
return TestPass;
}