From patchwork Sun Aug 4 15:31:04 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 20758 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 B7E17C323E for ; Sun, 4 Aug 2024 15:31:31 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id CEF0C63381; Sun, 4 Aug 2024 17:31:30 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="KNHuaRGU"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 0BF016192D for ; Sun, 4 Aug 2024 17:31:29 +0200 (CEST) Received: from pendragon.ideasonboard.com (81-175-209-231.bb.dnainternet.fi [81.175.209.231]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 03CD71BA for ; Sun, 4 Aug 2024 17:30:37 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1722785438; bh=3mSO3AP3H99LQi8Rzp2yWPr+zC7RK2pWz55iyKvjmvI=; h=From:To:Subject:Date:From; b=KNHuaRGUcYNPjZzQALlEfyikYTZrMs9OqioLrReMNbqzDCi2FYcquR1CBBNLBg9aQ gdRb6Lc29mOmrxux5s/oZF3pItiSQTTIgv3fAIIp5Gt9Q8p6dafzTuo5qx6NyJY/V0 mDZY+M9g0TjbEOVtNd4IwjwnmkpOZVU5/jKIycvc= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Subject: [PATCH v3 0/2] libcamera: Simplify error handling with ScopeExitActions class Date: Sun, 4 Aug 2024 18:31:04 +0300 Message-ID: <20240804153106.22167-1-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.44.2 MIME-Version: 1.0 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" Hello, Here's an attempt to resurect a patch series from nearly two years agoi. This small patch series stems from my review of "[PATCH 13/14] libcamera: pipeline: rkisp1: Factorize errors handling path on start()". While I agreed that the current error handling pattern in PipelineHandlerRkISP1::start() is fairly bad, I wasn't thrilled by usage of goto statements to fix it. This is an alternative proposal. The ScopeExitActions class introduced in patch 1/2 took multiple forms before reaching this one. I first experimented with a class that handled a single action and thus needed to be instantiated once per action. To achieve the equivalent of the ScopeExitActions::release() call I had to either add an 'if (ret)' statement to the lambda functions, or pass the ret variable to the constructor of the ScopeExitActions. I found ideas for syntactic sugar in https://github.com/yuri-kilochek/boost.scope_guard, but in the end, neither option made me very happy. Handling multiple actions with one ScopeExitActions instance makes the user code (in 2/2) simpler. The main drawback is the use of std::vector to store the actions, which requires dynamic allocation (and reallocation). I tried to find a different solution. One interesting approach used a ScopeExitGroup class instantiated at the beginning of the function, and a ScopeExit class that handled a single action, instantiated multiple times. The ScopeExit class was constructed with a pointer to the ScopeExitGroup, and only called the action in its destructor if the ScopeExitGroup hadn't been release()d. Unfortunately this didn't work well for patch 2/2, as the PipelineHandlerRkISP1::start() function needs to register an action in a sub-scope (within a if (...) { ... }). The corresponding ScopeExit instance thus got destroyed when exiting the sub-scope, not at the end of the function. Another completely different approach to error handling would be to make all the cleanup functions in PipelineHandlerRkISP1 idempotent, safe to be called when the corresponding operation hasn't been performed (e.g. streamOff() without a previous streamOn()). This idiom may result to better error handling through libcamera. If anyone thinks it could be better than a ScopeExitActions class, that would be enough to convince me to give it a try and burry ScopeExitActions. In v1 of the series the class had a defer() function (instead of an operator+=()), whose name was influenced by an interesting C extension proposal (https://hal.inria.fr/hal-03059076/document). It uses the name "guard" for the conceptual equivalent of the ScopeExitActions class, but that didn't convince me. I still wish the release() call wouldn't be needed, but I'm not as unhappy with it than in v1. This is error-prone as it could be forgotten, but the other options I can think of are worse; - Switch to the opposite, with cleanups disabled by default and an explicit call in the error paths. That could also be forgotten, resulting in missing cleanups in some error paths. The result would likely be worse, as error paths are less tested. - Require explicit calls in both the success and error paths, and complain loudly in the destructor if none of those functions have been called. That's equally error-prone due to undertesting of error paths. - Tying the explicit calls with the return statements, for instance by making the user return a Result type (any rust developer here ?), and adding two functions to ScopeExitActions, success and error, that return a Result. While the Result idiom may be interesting, it would be a much broader change. Laurent Pinchart (2): libcamera: utils: Add ScopeExitActions class pipeline: rkisp1: Use ScopeExitActions to simplify error handling in start include/libcamera/base/utils.h | 13 +++ src/libcamera/base/utils.cpp | 132 +++++++++++++++++++++++ src/libcamera/pipeline/rkisp1/rkisp1.cpp | 31 ++---- 3 files changed, 156 insertions(+), 20 deletions(-) base-commit: 19bbca3c0b376ba0183f5db53472c8c46cd402b5