From patchwork Tue Feb 2 22:10:50 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Niklas_S=C3=B6derlund?= X-Patchwork-Id: 11110 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 048FCBD161 for ; Tue, 2 Feb 2021 22:11:27 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 88B426843C; Tue, 2 Feb 2021 23:11:26 +0100 (CET) Received: from vsp-unauthed02.binero.net (vsp-unauthed02.binero.net [195.74.38.227]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 4B85568430 for ; Tue, 2 Feb 2021 23:11:25 +0100 (CET) X-Halon-ID: 96370623-65a3-11eb-b73f-0050569116f7 Authorized-sender: niklas.soderlund@fsdn.se Received: from bismarck.berto.se (p4fca2458.dip0.t-ipconnect.de [79.202.36.88]) by bin-vsp-out-03.atm.binero.net (Halon) with ESMTPA id 96370623-65a3-11eb-b73f-0050569116f7; Tue, 02 Feb 2021 23:11:24 +0100 (CET) From: =?utf-8?q?Niklas_S=C3=B6derlund?= To: libcamera-devel@lists.libcamera.org Date: Tue, 2 Feb 2021 23:10:50 +0100 Message-Id: <20210202221051.1740237-3-niklas.soderlund@ragnatech.se> X-Mailer: git-send-email 2.30.0 In-Reply-To: <20210202221051.1740237-1-niklas.soderlund@ragnatech.se> References: <20210202221051.1740237-1-niklas.soderlund@ragnatech.se> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v4 2/3] cam: event_loop: Execute events in the libevent loop 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" Cam uses libevent to deal with threads and idle loop while still implementing its own event queue. This creates issues when the event loop is terminated as it might get stuck in the idle loop if exit() is called while the thread is busy with dispatchCalls(). Solve this my removing the custom event execution and instead injecting the calls as events to the base event loop. Reported-by: Sebastian Fricke Signed-off-by: Niklas Söderlund Reviewed-by: Jacopo Mondi Reviewed-by: Laurent Pinchart --- src/cam/event_loop.cpp | 43 ++++++++++++++++++++---------------------- src/cam/event_loop.h | 6 +----- 2 files changed, 21 insertions(+), 28 deletions(-) diff --git a/src/cam/event_loop.cpp b/src/cam/event_loop.cpp index 3a2b665abdc063de..e84e437f1f8ff6d7 100644 --- a/src/cam/event_loop.cpp +++ b/src/cam/event_loop.cpp @@ -13,6 +13,13 @@ EventLoop *EventLoop::instance_ = nullptr; +static void dispatchCallback([[maybe_unused]] evutil_socket_t fd, + [[maybe_unused]] short flags, void *param) +{ + EventLoop *loop = static_cast(param); + loop->dispatchCall(); +} + EventLoop::EventLoop() { assert(!instance_); @@ -38,25 +45,13 @@ EventLoop *EventLoop::instance() int EventLoop::exec() { exitCode_ = -1; - exit_.store(false, std::memory_order_release); - - while (!exit_.load(std::memory_order_acquire)) { - dispatchCalls(); - event_base_loop(base_, EVLOOP_NO_EXIT_ON_EMPTY); - } - + event_base_loop(base_, EVLOOP_NO_EXIT_ON_EMPTY); return exitCode_; } void EventLoop::exit(int code) { exitCode_ = code; - exit_.store(true, std::memory_order_release); - interrupt(); -} - -void EventLoop::interrupt() -{ event_base_loopbreak(base_); } @@ -67,20 +62,22 @@ void EventLoop::callLater(const std::function &func) calls_.push_back(func); } - interrupt(); + struct event *event = event_new(base_, -1, 0, dispatchCallback, this); + event_active(event, 0, 0); } -void EventLoop::dispatchCalls() +void EventLoop::dispatchCall() { - std::unique_lock locker(lock_); + std::function call; - for (auto iter = calls_.begin(); iter != calls_.end(); ) { - std::function call = std::move(*iter); + { + std::unique_lock locker(lock_); + if (calls_.empty()) + return; - iter = calls_.erase(iter); - - locker.unlock(); - call(); - locker.lock(); + call = calls_.front(); + calls_.pop_front(); } + + call(); } diff --git a/src/cam/event_loop.h b/src/cam/event_loop.h index d0d5b5a53c830670..5f1cd88c2f5c830e 100644 --- a/src/cam/event_loop.h +++ b/src/cam/event_loop.h @@ -7,7 +7,6 @@ #ifndef __CAM_EVENT_LOOP_H__ #define __CAM_EVENT_LOOP_H__ -#include #include #include #include @@ -26,19 +25,16 @@ public: void exit(int code = 0); void callLater(const std::function &func); + void dispatchCall(); private: static EventLoop *instance_; struct event_base *base_; - std::atomic exit_; int exitCode_; std::list> calls_; std::mutex lock_; - - void interrupt(); - void dispatchCalls(); }; #endif /* __CAM_EVENT_LOOP_H__ */