From patchwork Fri Jul 31 18:14:14 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Umang Jain X-Patchwork-Id: 9119 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id D5FC1BD86F for ; Fri, 31 Jul 2020 18:14:18 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id A15D561EEF; Fri, 31 Jul 2020 20:14:17 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=uajain.com header.i=@uajain.com header.b="NTk0kvq3"; dkim-atps=neutral Received: from o1.f.az.sendgrid.net (o1.f.az.sendgrid.net [208.117.55.132]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id EEE28611A2 for ; Fri, 31 Jul 2020 20:14:15 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=uajain.com; h=from:subject:in-reply-to:references:mime-version:to:cc: content-transfer-encoding:content-type; s=s1; bh=YBXjP0n0lj5BCprVeWF7WmtypCWAldJAIa3SQ0eIJ6o=; b=NTk0kvq3Fo4w1tn9VPcMgJRsZ8qpEgZN299loTSbcJHwRpS0Dr8Xmjs7wG0DQ9DZz2of UKDsdJckY4m38s3px8PJIQIeYv5zT0oYmSLenIO1nev25gPt0owrXwQdENs4NBFw/tenBX tn5kdZHISBr6pT/Yz01HzkhULsN5vQsZE= Received: by filterdrecv-p3mdw1-7ff865655c-svvjh with SMTP id filterdrecv-p3mdw1-7ff865655c-svvjh-19-5F245F76-23 2020-07-31 18:14:14.634886421 +0000 UTC m=+172681.736483684 Received: from mail.uajain.com (unknown) by ismtpd0004p1maa1.sendgrid.net (SG) with ESMTP id r6JYpAVDSvCRRpNU_9H40Q Fri, 31 Jul 2020 18:14:14.242 +0000 (UTC) From: Umang Jain Date: Fri, 31 Jul 2020 18:14:14 +0000 (UTC) Message-Id: <20200731181410.99892-2-email@uajain.com> In-Reply-To: <20200731181410.99892-1-email@uajain.com> References: <20200731181410.99892-1-email@uajain.com> Mime-Version: 1.0 X-SG-EID: 1Q40EQ7YGir8a9gjSIAdTjhngY657NMk9ckeo4dbHZDiOpywc/L3L9rFqlwE4KPcIgOyDPOiX995eQdp4XFd3MB3kKT368qXzPWOoATU15gwFH1GX3Qhzp4UW2Y1Up/mNVFGoWyp0D1uU2FcX/ObcDnR2GbHI+CA3pXo6kcRfJksVy4ehV5v0XVOHD/o+BTUusOJ8DVu/K9O8VMDNHsL5NWPO9tEEHWVO+O9n8UMycXlhcTdlZInhjlZIGoqbRWblmwBohQ4p9ltxY7KNk1fiA== To: libcamera-devel@lists.libcamera.org Subject: [libcamera-devel] [PATCH v4 1/4] libcamera: thread: Support selective message dispatch to thread X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Extend the current dispatchMessages() to support dispatching of selective messsages according to the Message::Type passed in the function argument. dispatchMessages() can now be called explicitly to force deliver selected type's message to the thread for processing (typically when event loop is not running). Signed-off-by: Umang Jain Reviewed-by: Laurent Pinchart --- include/libcamera/internal/thread.h | 3 ++- src/libcamera/thread.cpp | 35 +++++++++++++++++++++-------- 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/include/libcamera/internal/thread.h b/include/libcamera/internal/thread.h index 7b59e58..f6367a8 100644 --- a/include/libcamera/internal/thread.h +++ b/include/libcamera/internal/thread.h @@ -14,6 +14,7 @@ #include +#include "libcamera/internal/message.h" #include "libcamera/internal/utils.h" namespace libcamera { @@ -47,7 +48,7 @@ public: EventDispatcher *eventDispatcher(); void setEventDispatcher(std::unique_ptr dispatcher); - void dispatchMessages(); + void dispatchMessages(Message::Type type = Message::Type::None); protected: int exec(); diff --git a/src/libcamera/thread.cpp b/src/libcamera/thread.cpp index d1750d7..87006a9 100644 --- a/src/libcamera/thread.cpp +++ b/src/libcamera/thread.cpp @@ -552,25 +552,42 @@ void Thread::removeMessages(Object *receiver) } /** - * \brief Dispatch all posted messages for this thread + * \brief Dispatch posted messages for this thread + * \param[in] type The message type + * + * This function immediately dispatches all the messages previously posted for + * this thread with postMessage() that match the message \a type. If the \a type + * is Message::Type::None, all messages are dispatched. */ -void Thread::dispatchMessages() +void Thread::dispatchMessages(Message::Type type) { MutexLocker locker(data_->messages_.mutex_); - while (!data_->messages_.list_.empty()) { - std::unique_ptr msg = std::move(data_->messages_.list_.front()); - data_->messages_.list_.pop_front(); - if (!msg) + std::list> &messages = data_->messages_.list_; + + for (auto iter = messages.begin(); iter != messages.end(); ) { + std::unique_ptr &msg = *iter; + + if (!msg) { + iter = data_->messages_.list_.erase(iter); + continue; + } + + if (type != Message::Type::None && msg->type() != type) { + ++iter; continue; + } - Object *receiver = msg->receiver_; - ASSERT(data_ == receiver->thread()->data_); + std::unique_ptr message = std::move(msg); + iter = data_->messages_.list_.erase(iter); + Object *receiver = message->receiver_; + ASSERT(data_ == receiver->thread()->data_); receiver->pendingMessages_--; locker.unlock(); - receiver->message(msg.get()); + receiver->message(message.get()); + message.reset(); locker.lock(); } } From patchwork Fri Jul 31 18:14:15 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Umang Jain X-Patchwork-Id: 9120 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 8BFE1BD86F for ; Fri, 31 Jul 2020 18:14:20 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 5B67861F05; Fri, 31 Jul 2020 20:14:20 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=uajain.com header.i=@uajain.com header.b="hCNPizlr"; dkim-atps=neutral Received: from o1.f.az.sendgrid.net (o1.f.az.sendgrid.net [208.117.55.132]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 0010C61EC4 for ; Fri, 31 Jul 2020 20:14:16 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=uajain.com; h=from:subject:in-reply-to:references:mime-version:to:cc: content-transfer-encoding:content-type; s=s1; bh=NvQR2ANfhOQyi9uIxHO5g1eCTnq0d+ZTD9G6Z/jGmKw=; b=hCNPizlrJPese6Osax1/gxvqLNvVbn0o0n7rciWPwz4EHqTC9yMAbjKTBMKrcvmJ/R7a Y8rXyy3uQD3j1vqXZ00UfrRul3hOzO6p0slgzycfBg2YeotMlhmDjTn1qWlej5QNlRZCtg QRNgwZXIS2RfboJTpE48CKtbTXY6KCPPs= Received: by filterdrecv-p3mdw1-7ff865655c-m2ckz with SMTP id filterdrecv-p3mdw1-7ff865655c-m2ckz-20-5F245F77-47 2020-07-31 18:14:15.646199566 +0000 UTC m=+172684.635387381 Received: from mail.uajain.com (unknown) by ismtpd0005p1maa1.sendgrid.net (SG) with ESMTP id 5LQm0FZoQ56T9x1aD4Aydw Fri, 31 Jul 2020 18:14:15.239 +0000 (UTC) From: Umang Jain Date: Fri, 31 Jul 2020 18:14:15 +0000 (UTC) Message-Id: <20200731181410.99892-3-email@uajain.com> In-Reply-To: <20200731181410.99892-1-email@uajain.com> References: <20200731181410.99892-1-email@uajain.com> Mime-Version: 1.0 X-SG-EID: 1Q40EQ7YGir8a9gjSIAdTjhngY657NMk9ckeo4dbHZDiOpywc/L3L9rFqlwE4KPcmGfnt8UlNcpPI7X/q8AWBi0v4Civ+FFQmNRO4Zj+oWM8hGsXYLVNiWbylcZ780/PZSeuusaZyomJpP7/PvNWCtjhswoxWfpLA1dMJt9DMjzql+u6oCVgF72I80PAY69WnwlawU/CxuOF1B3y5NLrE/sXc8UPCptud392e8wTQeuvgyZpYmE6aVFaMu7tSmYQdR7o0zB+CObjnfR+/6U2Vw== To: libcamera-devel@lists.libcamera.org Subject: [libcamera-devel] [PATCH v4 2/4] libcamera: object: Add deleteLater() support X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" This commit adds support to schedule the deletion of an Object to the thread it is bound to (similar to [1]). An Object getting destroyed by a different thread is considered as a violation as per the libcamera threading model. This will be useful for an Object where its ownership is shared via shared pointers in different threads. If the thread which drops the last reference of the Object is a different thread, the destructors get called in that particular thread, not the one Object is bound to. Hence, in order to resolve this kind of situation, the creation of shared pointer can be accompanied by a custom deleter which in turns use deleteLater() to ensure the Object is destroyed in its own thread. [1] https://doc.qt.io/qt-5/qobject.html#deleteLater Signed-off-by: Umang Jain Reviewed-by: Laurent Pinchart --- include/libcamera/internal/message.h | 1 + include/libcamera/object.h | 2 ++ src/libcamera/message.cpp | 2 ++ src/libcamera/object.cpp | 48 ++++++++++++++++++++++++++++ 4 files changed, 53 insertions(+) diff --git a/include/libcamera/internal/message.h b/include/libcamera/internal/message.h index 92ea64a..f1b133b 100644 --- a/include/libcamera/internal/message.h +++ b/include/libcamera/internal/message.h @@ -25,6 +25,7 @@ public: None = 0, InvokeMessage = 1, ThreadMoveMessage = 2, + DeferredDelete = 3, UserMessage = 1000, }; diff --git a/include/libcamera/object.h b/include/libcamera/object.h index 9a3dd07..a1882f0 100644 --- a/include/libcamera/object.h +++ b/include/libcamera/object.h @@ -27,6 +27,8 @@ public: Object(Object *parent = nullptr); virtual ~Object(); + void deleteLater(); + void postMessage(std::unique_ptr msg); templateparent_ = nullptr; } +/** + * \brief Schedule deletion of the instance in the thread it belongs to + * + * This function schedules deletion of the Object when control returns to the + * event loop that the object belongs to. This ensures the object is destroyed + * from the right context, as required by the libcamera threading model. + * + * If this function is called before the thread's event loop is started, the + * object will be deleted when the event loop starts. + * + * Deferred deletion can be used to control the destruction context with shared + * pointers. An object managed with shared pointers is deleted when the last + * reference is destroyed, which makes difficult to ensure through software + * design which context the deletion will take place in. With a custom deleter + * for the shared pointer using deleteLater(), the deletion can be guaranteed to + * happen in the thread the object is bound to. + * + * \code{.cpp} + * std::shared_ptr createObject() + * { + * struct Deleter : std::default_delete { + * void operator()(MyObject *obj) + * { + * delete obj; + * } + * }; + * + * MyObject *obj = new MyObject(); + * + * return std::shared_ptr(obj, Deleter()); + * } + * \endcode + * + * \context This function is \threadsafe. + */ +void Object::deleteLater() +{ + postMessage(std::make_unique(Message::DeferredDelete)); +} + /** * \brief Post a message to the object's thread * \param[in] msg The message @@ -144,6 +188,10 @@ void Object::message(Message *msg) break; } + case Message::DeferredDelete: + delete this; + break; + default: break; } From patchwork Fri Jul 31 18:14:18 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Umang Jain X-Patchwork-Id: 9121 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 2F4F9BD86F for ; Fri, 31 Jul 2020 18:14:23 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id F0507616FF; Fri, 31 Jul 2020 20:14:22 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=uajain.com header.i=@uajain.com header.b="HiR6M8Hg"; dkim-atps=neutral Received: from o1.f.az.sendgrid.net (o1.f.az.sendgrid.net [208.117.55.132]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id D04E7611A2 for ; Fri, 31 Jul 2020 20:14:19 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=uajain.com; h=from:subject:in-reply-to:references:mime-version:to:cc: content-transfer-encoding:content-type; s=s1; bh=tliDj6tjrNI3aLDqSMiIZntu529xthAawTbKFHUaav4=; b=HiR6M8HgbMT7x+2e5eCyByFls3nWGYSP/P0K+UBdZUiBjiT+B0KsyJ/NFHSKpHyoRCc8 xgYDJhtusorbKnqRTZOuoR6k1K4eIac3KeKb2XuCnNNSsl+1vx6P0HNMghnsB/OrSQHevp fB3S19Nf92bT5s7IuK/nM2dNnYV+b8ETA= Received: by filterdrecv-p3mdw1-canary-6c6ff5ff56-ngzws with SMTP id filterdrecv-p3mdw1-canary-6c6ff5ff56-ngzws-19-5F245F7A-2B 2020-07-31 18:14:18.684604995 +0000 UTC m=+176754.616199453 Received: from mail.uajain.com (unknown) by ismtpd0004p1maa1.sendgrid.net (SG) with ESMTP id 9Pe3IcQ-QciL4abFBGXmbw Fri, 31 Jul 2020 18:14:18.296 +0000 (UTC) From: Umang Jain Date: Fri, 31 Jul 2020 18:14:18 +0000 (UTC) Message-Id: <20200731181410.99892-4-email@uajain.com> In-Reply-To: <20200731181410.99892-1-email@uajain.com> References: <20200731181410.99892-1-email@uajain.com> Mime-Version: 1.0 X-SG-EID: 1Q40EQ7YGir8a9gjSIAdTjhngY657NMk9ckeo4dbHZDiOpywc/L3L9rFqlwE4KPcGYE5Iq+t2q0vZlJgodhIO7E4tCmj/R8GiO7znSV98Wx6NqD26y/vMGp0bm+HFnOnXp3b40OX0xIhBt9Xd8DLzOlb1OTvR86TGb2GbpgUxMQ6Bs0oV6a+H7+669T9knL/S3bQQTreuv4jAPGGfk6pRKQ57K4zaXnoamZbCFPiIBiLurGt2hAU1CiF0j4Aox4S9ZnnuYHJisa9qteZgM8HNYyLcAkz4IMW3Id1Vmk9UJw= To: libcamera-devel@lists.libcamera.org Subject: [libcamera-devel] [PATCH v4 3/4] tests: Add a test case for the Object::deleteLater() API, to verify X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" - the object is deleted from the correct thread - multiple deleteLater() calls delete the object once only Signed-off-by: Umang Jain Reviewed-by: Laurent Pinchart Signed-off-by: Laurent Pinchart --- test/meson.build | 1 + test/object-delete.cpp | 97 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 98 insertions(+) create mode 100644 test/object-delete.cpp diff --git a/test/meson.build b/test/meson.build index f41d6e7..f5aa144 100644 --- a/test/meson.build +++ b/test/meson.build @@ -34,6 +34,7 @@ internal_tests = [ ['hotplug-cameras', 'hotplug-cameras.cpp'], ['message', 'message.cpp'], ['object', 'object.cpp'], + ['object-delete', 'object-delete.cpp'], ['object-invoke', 'object-invoke.cpp'], ['pixel-format', 'pixel-format.cpp'], ['signal-threads', 'signal-threads.cpp'], diff --git a/test/object-delete.cpp b/test/object-delete.cpp new file mode 100644 index 0000000..a1a6f5c --- /dev/null +++ b/test/object-delete.cpp @@ -0,0 +1,97 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2020, Google Inc. + * + * object.cpp - Object deletion tests + */ + +#include + +#include + +#include "libcamera/internal/thread.h" + +#include "test.h" + +using namespace std; +using namespace libcamera; + +class TestObject : public Object +{ +public: + TestObject(unsigned int *count) + : deleteCount_(count) + { + } + + ~TestObject() + { + /* Count the deletions from the correct thread. */ + if (thread() == Thread::current()) + (*deleteCount_)++; + } + + unsigned int *deleteCount_; +}; + +class NewThread : public Thread +{ +public: + NewThread(Object *obj) + : object_(obj) + { + } + +protected: + void run() + { + object_->deleteLater(); + } + +private: + Object *object_; +}; + +class ObjectDeleteTest : public Test +{ +protected: + int run() + { + /* + * Test that deferred deletion is executed from the object's + * thread, not the caller's thread. + */ + unsigned int count = 0; + TestObject *obj = new TestObject(&count); + + NewThread thread(obj); + thread.start(); + thread.wait(); + + Thread::current()->dispatchMessages(Message::Type::DeferredDelete); + + if (count != 1) { + cout << "Failed to dispatch DeferredDelete (" << count << ")" << endl; + return TestFail; + } + + /* + * Test that multiple calls to deleteLater() delete the object + * once only. + */ + count = 0; + obj = new TestObject(&count); + obj->deleteLater(); + obj->deleteLater(); + + Thread::current()->dispatchMessages(Message::Type::DeferredDelete); + if (count != 1) { + cout << "Multiple deleteLater() failed (" << count << ")" << endl; + return TestFail; + } + + return TestPass; + } +}; + +TEST_REGISTER(ObjectDeleteTest) From patchwork Fri Jul 31 18:14:20 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Umang Jain X-Patchwork-Id: 9122 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 8F5B7BD879 for ; Fri, 31 Jul 2020 18:14:23 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 4BDF161F1B; Fri, 31 Jul 2020 20:14:23 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=uajain.com header.i=@uajain.com header.b="hdIwWGIg"; dkim-atps=neutral Received: from o1.f.az.sendgrid.net (o1.f.az.sendgrid.net [208.117.55.132]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 991A7611A2 for ; Fri, 31 Jul 2020 20:14:21 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=uajain.com; h=from:subject:in-reply-to:references:mime-version:to:cc: content-transfer-encoding:content-type; s=s1; bh=G8aUrpC88hKULTyVG1vQulK2b6B6VEjsFwMbdsHK/YY=; b=hdIwWGIgkAaT1ISjyCWRbRI9LGb8pNxkXUanp/HHiYMi8sHeEpA7OyreDITTJjX0NArP ZvMNzmdLFUjD/QDzmapZ+OkAkkxIJJG6giCd+6NcitkkFe7QUZQNMJjG2VBjwBLxSUWNw2 Vufj8WW8O6x1jcHN5Kf7tmbnsFaC/u0WY= Received: by filterdrecv-p3mdw1-7ff865655c-svvjh with SMTP id filterdrecv-p3mdw1-7ff865655c-svvjh-19-5F245F7C-4D 2020-07-31 18:14:20.612016378 +0000 UTC m=+172687.713613617 Received: from mail.uajain.com (unknown) by ismtpd0005p1hnd1.sendgrid.net (SG) with ESMTP id grWcS78XREGRNAHZ4crFTQ Fri, 31 Jul 2020 18:14:20.177 +0000 (UTC) From: Umang Jain Date: Fri, 31 Jul 2020 18:14:20 +0000 (UTC) Message-Id: <20200731181410.99892-5-email@uajain.com> In-Reply-To: <20200731181410.99892-1-email@uajain.com> References: <20200731181410.99892-1-email@uajain.com> Mime-Version: 1.0 X-SG-EID: 1Q40EQ7YGir8a9gjSIAdTjhngY657NMk9ckeo4dbHZDiOpywc/L3L9rFqlwE4KPcj9TjcWbOI2k4lJ0fKJaeeyGQUzl0aZlU4nehjRj03/+6xzpI2FEkb70FYM1DwSIZgISXCR0j8IJXDzCROJ0Ix5AxU5khER5WZoxJ47OpOcEyJg7MS3cLo469M1zAho7xfkhluQzEytX8/lB8Wt/RD+LmASzQiSVt7T7+L3ujfLNdw3vxHDVUohfXyJ4BfFV1yMoxFhV0ZesepVGbmmlueA== To: libcamera-devel@lists.libcamera.org Subject: [libcamera-devel] [PATCH v4 4/4] libcamera: camera: Ensure deletion via deleteLater() X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Object::deleteLater() ensures that the deletion of the Object takes place in a thread it is bound to. Deleting the Object in a different thread is a violation according to the libcamera threading model. On hot-unplug of a currently streaming camera, the last reference of Camera when dropped from the application thread (for e.g. QCam's thread), the destructor is then called from this thread. This is not allowed by the libcamera threading model. Camera is meant to be deleted in the thread it is bound to - in this case the CameraManager's thread. Signed-off-by: Umang Jain Reviewed-by: Laurent Pinchart --- include/libcamera/camera.h | 3 ++- src/libcamera/camera.cpp | 2 +- src/libcamera/camera_manager.cpp | 6 +++++- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/include/libcamera/camera.h b/include/libcamera/camera.h index 4d1a4a9..7dd23d7 100644 --- a/include/libcamera/camera.h +++ b/include/libcamera/camera.h @@ -13,6 +13,7 @@ #include #include +#include #include #include #include @@ -66,7 +67,7 @@ protected: std::vector config_; }; -class Camera final : public std::enable_shared_from_this +class Camera final : public Object, public std::enable_shared_from_this { public: static std::shared_ptr create(PipelineHandler *pipe, diff --git a/src/libcamera/camera.cpp b/src/libcamera/camera.cpp index 69a1b44..034f341 100644 --- a/src/libcamera/camera.cpp +++ b/src/libcamera/camera.cpp @@ -464,7 +464,7 @@ std::shared_ptr Camera::create(PipelineHandler *pipe, struct Deleter : std::default_delete { void operator()(Camera *camera) { - delete camera; + camera->deleteLater(); } }; diff --git a/src/libcamera/camera_manager.cpp b/src/libcamera/camera_manager.cpp index f60491d..c45bf33 100644 --- a/src/libcamera/camera_manager.cpp +++ b/src/libcamera/camera_manager.cpp @@ -164,9 +164,13 @@ void CameraManager::Private::cleanup() /* * Release all references to cameras to ensure they all get destroyed - * before the device enumerator deletes the media devices. + * before the device enumerator deletes the media devices. Cameras are + * destroyed via Object::deleteLater() API, hence we need to explicitly + * process deletion requests from the thread's message queue as the event + * loop is not in action here. */ cameras_.clear(); + dispatchMessages(Message::Type::DeferredDelete); enumerator_.reset(nullptr); }