Patch Detail
Show a patch.
GET /api/1.1/patches/22434/?format=api
{ "id": 22434, "url": "https://patchwork.libcamera.org/api/1.1/patches/22434/?format=api", "web_url": "https://patchwork.libcamera.org/patch/22434/", "project": { "id": 1, "url": "https://patchwork.libcamera.org/api/1.1/projects/1/?format=api", "name": "libcamera", "link_name": "libcamera", "list_id": "libcamera_core", "list_email": "libcamera-devel@lists.libcamera.org", "web_url": "", "scm_url": "", "webscm_url": "" }, "msgid": "<20241220150759.709756-9-pobrn@protonmail.com>", "date": "2024-12-20T15:08:37", "name": "[RFC,v1,08/12] apps: lc-compliance: Remove libevent dependency", "commit_ref": null, "pull_url": null, "state": "superseded", "archived": false, "hash": "3d77cbcd2de06852ecfd4f4b536289273ef863d4", "submitter": { "id": 133, "url": "https://patchwork.libcamera.org/api/1.1/people/133/?format=api", "name": "Pőcze Barnabás", "email": "pobrn@protonmail.com" }, "delegate": null, "mbox": "https://patchwork.libcamera.org/patch/22434/mbox/", "series": [ { "id": 4923, "url": "https://patchwork.libcamera.org/api/1.1/series/4923/?format=api", "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=4923", "date": "2024-12-20T15:08:03", "name": "apps: lc-compliance: Multi-stream tests", "version": 1, "mbox": "https://patchwork.libcamera.org/series/4923/mbox/" } ], "comments": "https://patchwork.libcamera.org/api/patches/22434/comments/", "check": "pending", "checks": "https://patchwork.libcamera.org/api/patches/22434/checks/", "tags": {}, "headers": { "Return-Path": "<libcamera-devel-bounces@lists.libcamera.org>", "X-Original-To": "parsemail@patchwork.libcamera.org", "Delivered-To": "parsemail@patchwork.libcamera.org", "Received": [ "from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id C8E8CC3272\n\tfor <parsemail@patchwork.libcamera.org>;\n\tFri, 20 Dec 2024 15:08:44 +0000 (UTC)", "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 64145684B2;\n\tFri, 20 Dec 2024 16:08:44 +0100 (CET)", "from mail-40134.protonmail.ch (mail-40134.protonmail.ch\n\t[185.70.40.134])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 0294C684AE\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 20 Dec 2024 16:08:41 +0100 (CET)" ], "Authentication-Results": "lancelot.ideasonboard.com;\n\tdkim=fail reason=\"signature verification failed\" (2048-bit key;\n\tunprotected) header.d=protonmail.com header.i=@protonmail.com\n\theader.b=\"ZoDjLvxh\"; dkim-atps=neutral", "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=protonmail.com;\n\ts=protonmail3; t=1734707320; x=1734966520;\n\tbh=T1ArgVyr9LxnraRalmGQSwNWbt3n6iSqk9UDRW1FMM8=;\n\th=Date:To:From:Subject:Message-ID:In-Reply-To:References:\n\tFeedback-ID:From:To:Cc:Date:Subject:Reply-To:Feedback-ID:\n\tMessage-ID:BIMI-Selector:List-Unsubscribe:List-Unsubscribe-Post;\n\tb=ZoDjLvxhG56N2fBRxXgeuDse3QR+gblciFP71dreMHmswTzgR7ECSZcf6kQSJAn2f\n\tgGbodGVXWRjl19QRtBsRVrhzWE2VGAXnhV/3D7aW8KdiTwjSFkj7vmKISN3coC2ekH\n\tDoJNrcHb/uQVECErp6rIMz04oGMEFKHxS5PJVrVXi4X6GnFcE/1AE3uupkaNENVHP5\n\tn4Fa8j5iz3FK0kCeAoYaWMiDfbHvy7cJKqKJ8MBhnIteFpXYCLK/KbvZoSgOihhjOC\n\t6aqfo8Gd4lRA8QhSUzldmYR7GDyNp5SSmVjk3hIOUCfBhXkft9MQC3HCcfx6xGrdpH\n\tR5btGgGe7dCmA==", "Date": "Fri, 20 Dec 2024 15:08:37 +0000", "To": "libcamera-devel@lists.libcamera.org", "From": "=?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= <pobrn@protonmail.com>", "Subject": "[RFC PATCH v1 08/12] apps: lc-compliance: Remove libevent dependency", "Message-ID": "<20241220150759.709756-9-pobrn@protonmail.com>", "In-Reply-To": "<20241220150759.709756-1-pobrn@protonmail.com>", "References": "<20241220150759.709756-1-pobrn@protonmail.com>", "Feedback-ID": "20568564:user:proton", "X-Pm-Message-ID": "5e7dddb2a7e18cb9935e602b516beae085bcff46", "MIME-Version": "1.0", "Content-Type": "text/plain; charset=utf-8", "Content-Transfer-Encoding": "quoted-printable", "X-BeenThere": "libcamera-devel@lists.libcamera.org", "X-Mailman-Version": "2.1.29", "Precedence": "list", "List-Id": "<libcamera-devel.lists.libcamera.org>", "List-Unsubscribe": "<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>", "List-Archive": "<https://lists.libcamera.org/pipermail/libcamera-devel/>", "List-Post": "<mailto:libcamera-devel@lists.libcamera.org>", "List-Help": "<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>", "List-Subscribe": "<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>", "Errors-To": "libcamera-devel-bounces@lists.libcamera.org", "Sender": "\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>" }, "content": "libevent is only used as a way to notify the main thread from\nthe CameraManager thread when the capture should be terminated.\n\nNot only is libevent not really necessary and instead can be\nreplaced with a simple combination of C++ STL parts, the current\nusage is prone to race conditions.\n\nSpecifically, the camera's `queueRequest()` might complete the\nrequest before the main thread could set the `loop_` member\nvariable and synchronize with the thread. This is a data race,\npractically resulting in a nullptr or dangling pointer dereference.\n\nThis can easily be triggered by inserting a sufficiently large\ntimeout before `loop_ = new EventLoop;`:\n\n [46:43:40.529620351] [671833] DEBUG Request request.cpp:129 Request(4:C:0/1:0)\n ../src/apps/lc-compliance/helpers/capture.cpp:140:14: runtime error: member call on null pointer of type 'struct EventLoop'\n 0 0x632c3e82f81a in CaptureBalanced::requestComplete(libcamera::Request*) ../src/apps/lc-compliance/helpers/capture.cpp:140\n\nSigned-off-by: Barnabás Pőcze <pobrn@protonmail.com>\n---\n README.rst | 2 +-\n src/apps/lc-compliance/helpers/capture.cpp | 23 ++++++------\n src/apps/lc-compliance/helpers/capture.h | 42 +++++++++++++++++++---\n src/apps/lc-compliance/meson.build | 7 ++--\n src/apps/meson.build | 5 ---\n 5 files changed, 53 insertions(+), 26 deletions(-)", "diff": "diff --git a/README.rst b/README.rst\nindex 4068c6cc8..f1749be97 100644\n--- a/README.rst\n+++ b/README.rst\n@@ -97,7 +97,7 @@ for Python bindings: [optional]\n pybind11-dev\n \n for lc-compliance: [optional]\n- libevent-dev libgtest-dev\n+ libgtest-dev\n \n for abi-compat.sh: [optional]\n abi-compliance-checker\ndiff --git a/src/apps/lc-compliance/helpers/capture.cpp b/src/apps/lc-compliance/helpers/capture.cpp\nindex 91c4d4400..b473e0773 100644\n--- a/src/apps/lc-compliance/helpers/capture.cpp\n+++ b/src/apps/lc-compliance/helpers/capture.cpp\n@@ -12,7 +12,7 @@\n using namespace libcamera;\n \n Capture::Capture(std::shared_ptr<Camera> camera)\n-\t: loop_(nullptr), camera_(std::move(camera)),\n+\t: camera_(std::move(camera)),\n \t allocator_(camera_)\n {\n }\n@@ -52,6 +52,8 @@ void Capture::start()\n \n \tcamera_->requestCompleted.connect(this, &Capture::requestComplete);\n \n+\tresult_.reset();\n+\n \tASSERT_EQ(camera_->start(), 0) << \"Failed to start camera\";\n }\n \n@@ -62,6 +64,8 @@ void Capture::stop()\n \n \tcamera_->stop();\n \n+\tresult_.reset();\n+\n \tcamera_->requestCompleted.disconnect(this);\n \n \tStream *stream = config_->at(0).stream();\n@@ -108,11 +112,10 @@ void CaptureBalanced::capture(unsigned int numRequests)\n \t}\n \n \t/* Run capture session. */\n-\tloop_ = new EventLoop();\n-\tloop_->exec();\n+\tint status = result_.wait();\n \tstop();\n-\tdelete loop_;\n \n+\tASSERT_EQ(status, 0);\n \tASSERT_EQ(captureCount_, captureLimit_);\n }\n \n@@ -132,13 +135,13 @@ void CaptureBalanced::requestComplete(Request *request)\n \n \tcaptureCount_++;\n \tif (captureCount_ >= captureLimit_) {\n-\t\tloop_->exit(0);\n+\t\tresult_.set(0);\n \t\treturn;\n \t}\n \n \trequest->reuse(Request::ReuseBuffers);\n \tif (queueRequest(request))\n-\t\tloop_->exit(-EINVAL);\n+\t\tresult_.set(-EINVAL);\n }\n \n /* CaptureUnbalanced */\n@@ -171,10 +174,8 @@ void CaptureUnbalanced::capture(unsigned int numRequests)\n \t}\n \n \t/* Run capture session. */\n-\tloop_ = new EventLoop();\n-\tint status = loop_->exec();\n+\tint status = result_.wait();\n \tstop();\n-\tdelete loop_;\n \n \tASSERT_EQ(status, 0);\n }\n@@ -183,7 +184,7 @@ void CaptureUnbalanced::requestComplete(Request *request)\n {\n \tcaptureCount_++;\n \tif (captureCount_ >= captureLimit_) {\n-\t\tloop_->exit(0);\n+\t\tresult_.set(0);\n \t\treturn;\n \t}\n \n@@ -192,5 +193,5 @@ void CaptureUnbalanced::requestComplete(Request *request)\n \n \trequest->reuse(Request::ReuseBuffers);\n \tif (camera_->queueRequest(request))\n-\t\tloop_->exit(-EINVAL);\n+\t\tresult_.set(-EINVAL);\n }\ndiff --git a/src/apps/lc-compliance/helpers/capture.h b/src/apps/lc-compliance/helpers/capture.h\nindex a4cc3a99e..8582ade8e 100644\n--- a/src/apps/lc-compliance/helpers/capture.h\n+++ b/src/apps/lc-compliance/helpers/capture.h\n@@ -7,12 +7,13 @@\n \n #pragma once\n \n+#include <condition_variable>\n #include <memory>\n+#include <mutex>\n+#include <optional>\n \n #include <libcamera/libcamera.h>\n \n-#include \"../common/event_loop.h\"\n-\n class Capture\n {\n public:\n@@ -27,12 +28,45 @@ protected:\n \n \tvirtual void requestComplete(libcamera::Request *request) = 0;\n \n-\tEventLoop *loop_;\n-\n \tstd::shared_ptr<libcamera::Camera> camera_;\n \tlibcamera::FrameBufferAllocator allocator_;\n \tstd::unique_ptr<libcamera::CameraConfiguration> config_;\n \tstd::vector<std::unique_ptr<libcamera::Request>> requests_;\n+\n+\tstruct\n+\t{\n+\tprivate:\n+\t\tstd::mutex mutex_;\n+\t\tstd::condition_variable cv_;\n+\t\tstd::optional<int> value_;\n+\n+\tpublic:\n+\t\tint wait()\n+\t\t{\n+\t\t\tstd::unique_lock guard(mutex_);\n+\n+\t\t\tcv_.wait(guard, [&] {\n+\t\t\t\treturn value_.has_value();\n+\t\t\t});\n+\n+\t\t\treturn *value_;\n+\t\t}\n+\n+\t\tvoid set(int value)\n+\t\t{\n+\t\t\tstd::unique_lock guard(mutex_);\n+\n+\t\t\tif (!value_)\n+\t\t\t\tvalue_ = value;\n+\n+\t\t\tcv_.notify_all();\n+\t\t}\n+\n+\t\tvoid reset()\n+\t\t{\n+\t\t\tvalue_.reset();\n+\t\t}\n+\t} result_;\n };\n \n class CaptureBalanced : public Capture\ndiff --git a/src/apps/lc-compliance/meson.build b/src/apps/lc-compliance/meson.build\nindex b1f605f33..0884bc6ca 100644\n--- a/src/apps/lc-compliance/meson.build\n+++ b/src/apps/lc-compliance/meson.build\n@@ -4,13 +4,11 @@ libgtest = dependency('gtest', version : '>=1.10.0',\n required : get_option('lc-compliance'),\n fallback : ['gtest', 'gtest_dep'])\n \n-if opt_lc_compliance.disabled() or not libevent.found() or not libgtest.found()\n- lc_compliance_enabled = false\n+lc_compliance_enabled = opt_lc_compliance.allowed() and libgtest.found()\n+if not lc_compliance_enabled\n subdir_done()\n endif\n \n-lc_compliance_enabled = true\n-\n lc_compliance_sources = files([\n 'environment.cpp',\n 'helpers/capture.cpp',\n@@ -29,7 +27,6 @@ lc_compliance = executable('lc-compliance', lc_compliance_sources,\n dependencies : [\n libatomic,\n libcamera_public,\n- libevent,\n libgtest,\n ],\n include_directories : lc_compliance_includes,\ndiff --git a/src/apps/meson.build b/src/apps/meson.build\nindex af632b9a7..252491441 100644\n--- a/src/apps/meson.build\n+++ b/src/apps/meson.build\n@@ -3,12 +3,7 @@\n opt_cam = get_option('cam')\n opt_lc_compliance = get_option('lc-compliance')\n \n-# libevent is needed by cam and lc-compliance. As they are both feature options,\n-# they can't be combined with simple boolean logic.\n libevent = dependency('libevent_pthreads', required : opt_cam)\n-if not libevent.found()\n- libevent = dependency('libevent_pthreads', required : opt_lc_compliance)\n-endif\n \n libtiff = dependency('libtiff-4', required : false)\n \n", "prefixes": [ "RFC", "v1", "08/12" ] }