From patchwork Tue Jan 19 23:33:15 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: 10903 X-Patchwork-Delegate: niklas.soderlund@ragnatech.se 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 ED3C9C0F1C for ; Tue, 19 Jan 2021 23:33:25 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id CAB4A68170; Wed, 20 Jan 2021 00:33:25 +0100 (CET) Received: from bin-mail-out-05.binero.net (bin-mail-out-05.binero.net [195.74.38.228]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 2A1AB6010B for ; Wed, 20 Jan 2021 00:33:24 +0100 (CET) X-Halon-ID: b5de9dfd-5aae-11eb-a076-005056917f90 Authorized-sender: niklas.soderlund@fsdn.se Received: from bismarck.berto.se (p4fca2458.dip0.t-ipconnect.de [79.202.36.88]) by bin-vsp-out-02.atm.binero.net (Halon) with ESMTPA id b5de9dfd-5aae-11eb-a076-005056917f90; Wed, 20 Jan 2021 00:33:22 +0100 (CET) From: =?utf-8?q?Niklas_S=C3=B6derlund?= To: libcamera-devel@lists.libcamera.org Date: Wed, 20 Jan 2021 00:33:15 +0100 Message-Id: <20210119233315.3305649-1-niklas.soderlund@ragnatech.se> X-Mailer: git-send-email 2.30.0 MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2] cam: event_loop: Stop processing calls when event loop is exiting 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" Terminating the event loop with EventLoop::exit() does not grantee that it will terminate. If the event loops 'call later' queue can be kept non-empty by continuously queuing new calls using EventLoop::callLater() either from a different thread or from callbacks in the loop itself EventLoop::dispatchCalls() will never complete and the loop will run forever. Solve this by evaluating the exit condition between each callback and only enter the idle loop if there are no callbacks to process. Reported-by: Sebastian Fricke Fixes: f49e93338b6309a6 ("cam: event_loop: Add deferred calls support") Signed-off-by: Niklas Söderlund --- * Changes since v1 - Was [PATCH 0/2] cam: Fix races in event loop and long request processing times - Rework dispatchCalls() instead of callLater() for a simpler fix. --- src/cam/event_loop.cpp | 22 +++++++++++++--------- src/cam/event_loop.h | 2 +- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/cam/event_loop.cpp b/src/cam/event_loop.cpp index 94c5d1d362455f33..18786b4500be9b6f 100644 --- a/src/cam/event_loop.cpp +++ b/src/cam/event_loop.cpp @@ -41,7 +41,9 @@ int EventLoop::exec() exit_.store(false, std::memory_order_release); while (!exit_.load(std::memory_order_acquire)) { - dispatchCalls(); + if (dispatchCall()) + continue; + event_base_loop(event_, EVLOOP_NO_EXIT_ON_EMPTY); } @@ -70,17 +72,19 @@ void EventLoop::callLater(const std::function &func) interrupt(); } -void EventLoop::dispatchCalls() +bool EventLoop::dispatchCall() { std::unique_lock locker(lock_); - for (auto iter = calls_.begin(); iter != calls_.end(); ) { - std::function call = std::move(*iter); + if (calls_.empty()) + return false; - iter = calls_.erase(iter); + auto iter = calls_.begin(); + std::function call = std::move(*iter); + calls_.erase(iter); - locker.unlock(); - call(); - locker.lock(); - } + locker.unlock(); + call(); + + return true; } diff --git a/src/cam/event_loop.h b/src/cam/event_loop.h index 408073c50594d09d..b84e1c9e432086e3 100644 --- a/src/cam/event_loop.h +++ b/src/cam/event_loop.h @@ -38,7 +38,7 @@ private: std::mutex lock_; void interrupt(); - void dispatchCalls(); + bool dispatchCall(); }; #endif /* __CAM_EVENT_LOOP_H__ */