[libcamera-devel] [PATCH] libcamera: camera: Fail to configure on mis-configured streams

Laurent Pinchart laurent.pinchart at ideasonboard.com
Tue Jul 30 07:49:13 CEST 2019


Hi Niklas,

On Tue, Jul 30, 2019 at 07:37:15AM +0200, Niklas Söderlund wrote:
> On 2019-07-30 07:09:05 +0300, Laurent Pinchart wrote:
> > On Mon, Jul 22, 2019 at 10:54:26AM +0100, Kieran Bingham wrote:
> >> On 20/07/2019 14:22, Niklas Söderlund wrote:
> >>> On 2019-07-19 08:33:46 +0100, Kieran Bingham wrote:
> >>>> On 18/07/2019 14:56, Laurent Pinchart wrote:
> >>>>> On Thu, Jul 18, 2019 at 05:27:54AM +0100, Kieran Bingham wrote:
> >>>>>> Uses of LOG(x, Fatal) and ASSERT() should be capable of continuing
> >>>>>> without crashing.
> >>>>>>
> >>>>>> Camera::configure() validates that each StreamConfiguration has a
> >>>>>> Stream* and reports a Fatal error otherwise. The code then goes on to
> >>>>>> dereference the Stream pointer which will be a nullptr in the event of
> >>>>>> the Fatal error being triggered.
> >>>>>>
> >>>>>> In release builds, ASSERTS are compiled out, and LOG(x, Fatal) should
> >>>>>> attempt to continue or report the error up the call-stack.
> >>>>>>
> >>>>>> Make Camera::configure() return an error in the event that the Stream*
> >>>>>> is not valid. This will cause the configure operation to fail and the
> >>>>>> application will be notified just as other errors in the
> >>>>>> Camera::configure() operation do.
> >>>>>>
> >>>>>> Signed-off-by: Kieran Bingham <kieran.bingham at ideasonboard.com>
> >>>>>> ---
> >>>>>>  src/libcamera/camera.cpp | 4 +++-
> >>>>>>  1 file changed, 3 insertions(+), 1 deletion(-)
> >>>>>>
> >>>>>> diff --git a/src/libcamera/camera.cpp b/src/libcamera/camera.cpp
> >>>>>> index 76c737cb9381..7ad9e0e48686 100644
> >>>>>> --- a/src/libcamera/camera.cpp
> >>>>>> +++ b/src/libcamera/camera.cpp
> >>>>>> @@ -672,9 +672,11 @@ int Camera::configure(CameraConfiguration *config)
> >>>>>>  	activeStreams_.clear();
> >>>>>>  	for (const StreamConfiguration &cfg : *config) {
> >>>>>>  		Stream *stream = cfg.stream();
> >>>>>> -		if (!stream)
> >>>>>> +		if (!stream) {
> >>>>>>  			LOG(Camera, Fatal)
> >>>>>>  				<< "Pipeline handler failed to update stream configuration";
> >>>>>> +			return -EINVAL;
> >>>>>
> >>>>> Overall this makes sense, but I wonder if -EINVAL is the appropriate
> >>>>> error code. The issue at hand is that the pipeline handler is buggy. A
> >>>>> specific error code to denote errors that are not supposed to happen
> >>>>> ever would be best I think (and bonus points if we could use that error
> >>>>> code consistently through libcamera).
> >>>>
> >>>> -EPIPE 'sounds' appropriate, because we have a broken pipe if we don't
> >>>> have a stream pointer - as long as that doesn't get too confusing
> >>>> against other types of pipe :)
> >>>>
> >>>> Or we could use: "ESTRPIPE 86 Streams pipe error"?
> >>>>
> >>>> But then again for a generic 'Fatal' error code we could choose one of:
> >>>>
> >>>>   EOWNERDEAD 130 Owner died
> >>>>   ENOTRECOVERABLE 131 State not recoverable
> >>>>
> >>>> I quite like both of those for a 'fatal' error.
> > 
> > I quite like ENOTRECOVERABLE too.
> > 
> >>> Is this not an academic question? As LOG(..., Fatal) will never return 
> >>> and terminate the application?
> >> 
> >> Currently, you are correct - but while discussing with Laurent on
> >> another patch somewhere, or perhaps it was IRC - I can't recall, we
> >> realised that we might have to make LOG(x, Fatal) *non-fatal* on release
> >> builds.
> >> 
> >> (Just as assertions are compiled out in release builds)
> >> 
> >> It might be that we leave this to a packaging policy as well.
> >> 
> >> Anyway, this is the only part of the code that in the event of the
> >> failure being detected would then go on to do a null-dereference - so I
> >> thought the small fix up was worth it.
> >> 
> >> Perhaps I should add a comment before the return explaining that this
> >> code is unreachable in debug builds, but could be enabled in future
> >> release builds?
> > 
> > I think mentioning it in the commit log is enough, there's no need to
> > sprinkle copies of the information through the code.
> 
> I'm not sure I like the idea of allowing continued execution after a 
> LOG(..., Fatal) in release builds. It feels a bit like Java, whenever 
> one looks at a process logs it's sprinkled with unhandled expectation 
> log messages and trying to narrow down a problem is impossible so one 
> just gives up and once prejudice against the language is reinforced ;-)
> 
> I'm not against changing/removing LOG(..., Fatal) so that it always 
> allow continued execution after it's been called. But I think it should 
> be the same behavior always, we will have enough trouble as it is to 
> test all different error paths :-)
> 
> ASSERT() for me is different, it's usually at the start of functions and 
> could be in hot paths and do not alter the execution order of functions 
> so it make sens to disable them in release builds as it decreases the 
> execution time. While I think of LOG(..., Fatal) as BUG() if it happens 
> we are in deep shit and there is no point in trying to recover from it.

>From a libcamera point of view that's true, but from an application
point of view there may be a use for closing gracefully and saving data.
For me LOG(..., Fatal) is a LOG() + ASSERT(), but if we have to keep the
same behaviour in both release and debug builds, I would prefer removing
the std::abort() call completely from LOG(..., Fatal).

> >>> If we need a return statement to keep analysers happy add one in the LOG 
> >>> macro. The return code could be EXIT_FAILURE.
> >> 
> >> Eeeep - no - I really don't want to have a macro which returns implicitly.
> >> 
> >> I would really prefer to keep return paths explicit.
> > 
> > I also dislike hiding return statements in macros, even if it could help
> > standardising the return value. Let's also note that LOG(..., Fatal) can
> > be used in functions returning any type, so we can't simply return
> > -EWHATEVER there.
> > 
> >>>>>> +		}
> >>>>>>  
> >>>>>>  		stream->configuration_ = cfg;
> >>>>>>  		activeStreams_.insert(stream);

-- 
Regards,

Laurent Pinchart


More information about the libcamera-devel mailing list