[libcamera-devel] [PATCH 0/2] libcamera: Simplify error handling with Cleaner class
Kieran Bingham
kieran.bingham at ideasonboard.com
Tue Oct 11 16:51:19 CEST 2022
Quoting Laurent Pinchart via libcamera-devel (2022-10-04 03:18:40)
> Hello,
>
> 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 Cleaner 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 Cleaner::clear() call I had to either add
> an 'if (ret)' statement to the lambda functions, or pass the ret
> variable to the constructor of the Cleaner. 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 deferred cleanup actions with one Cleaner instance
> makes the user code (in 2/2) simpler. The "defer" name for the
> Cleaner::defer() function 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 Cleaner class, but that
> didn't convince me. I'm not sure to really like the "Cleaner" name
> though, alternative naming proposals are welcome.
I'm not sure I like 'Cleaner' either. To me, this looks very much like
the scope_exit experimental C++ features:
https://en.cppreference.com/w/cpp/experimental/scope_exit
I like the ability to add multiple cleanups to a single instance though.
https://github.com/SergiusTheBest/ScopeExit is another interesting
implementation, but bases the choice for a Success or Failed return
using exceptions, so that's not of any use to us.
I (almost) like the syntatic sugar that means lambda's are hidden away:
https://github.com/SergiusTheBest/ScopeExit/blob/master/include/ScopeExit/ScopeExit.h
SCOPE_EXIT{ cout << "hello"; }; // will be called at the scope exit
Which could easily be ScopeExit { }; ... but that's creating a separate
instance for each declaration which wouldn't be easy to 'clean up' or
cancel..., so I think that's not any better.
> One point I'm not happy with is the need to call Cleaner::clear() in the
> success path. This is error-prone as it could be forgotten. We could
> switch to the opposite, with cleanups disabled by default and an
> explicit call in the error paths, but that could also be forgotten,
> resulting in missing cleanups in some error paths. The result would
> possibly be worse, as error paths are less tested. Another option would
> be to require explicit calls in both the success and error paths, and
> complain loudly in the destructor if none of those functions have been
> called. I'm not sure to be convinced it would be the best idea, although
Explicitly requiring either Cleaner.success() or Cleaner.fail() with an
error if one isn't called is interesting, but I am weary that then
someone will end up simply calling the 'wrong one' on a code path ...
But maybe that's worrying about 'possible' bugs, rather than actual
bugs.
> finding good names for the success/error functions may help. Alternative
> ideas are welcome too, as well as opinions regarding whether this is
> worth it or not.
If there is automatic operations at exit, I'd call it AtScopeExit or
ScopeExit ...
and use something like
(At?)ScopeExit e;
e.defer([&]{ std::out << "Failed" << std::endl; });
if (fail)
return -EINVAL;
e.cancel();
return 0;
But it's also just 'deferred work' so perhaps DeferredWorker would be a
better class name than Cleaner if it is enforced to be called at both
success/failure paths.
Remembering to cleanup before a successful exit is a pain, but I bet
that's easier to catch if it goes wrong than the alternative, as the
'success' path is likely to be more often used... So I actually think
this would be 'safer'?
Anyway, overall - I like the idea of a cleanup helper...
--
Kieran
>
> Laurent Pinchart (2):
> libcamera: utils: Add Cleaner class
> pipeline: rkisp1: Use utils::Cleaner to simplify error handling in
> start
>
> include/libcamera/base/utils.h | 13 +++
> src/libcamera/base/utils.cpp | 130 +++++++++++++++++++++++
> src/libcamera/pipeline/rkisp1/rkisp1.cpp | 31 ++----
> 3 files changed, 154 insertions(+), 20 deletions(-)
>
> --
> Regards,
>
> Laurent Pinchart
>
More information about the libcamera-devel
mailing list