[RFC] delayed_controls: avoid reading undefined control value

Laurent Pinchart laurent.pinchart at ideasonboard.com
Wed Dec 11 08:43:29 CET 2024


(CC'ing Naush for the question related to the Raspberry Pi
implementation)

On Tue, Dec 10, 2024 at 10:39:50PM +0000, Kieran Bingham wrote:
> Quoting Stanislaw Gruszka (2024-12-06 11:27:43)
> > Limit ControlRingBuffer index by number of queued entries in order do
> > avoid reading undefined control value with type ControlTypeNone .
> > 
> > It can happen at the begging of streaming when ControlRingBuffer is
> 
> s/begging/beginning/
> 
> > not yet filled and there are errors on CSI-2 bus resulting dropping
> > frames. Then we can call to DelayedControls::get() with frame number
> > that exceed number of saved entries and get below assertion failure:
> > 
> > ../src/libcamera/delayed_controls.cpp:227:
> > libcamera::ControlList libcamera::DelayedControls::get(uint32_t):
> > Assertion `info.type() != ControlTypeNone' failed
> > 
> > Bug: https://bugs.libcamera.org/show_bug.cgi?id=241
> > Signed-off-by: Stanislaw Gruszka <stanislaw.gruszka at linux.intel.com>
> > ---
> > Notes: When debugging this I notice that the push() and get() are
> > done in different threads. Maybe mutex should be
> > used? Not sure how synchronization works for mojom signals
> > handlers.

The comment related to the SoftwareISP::inputBufferReady signal, in the
SimpleCameraData::init() function, possibly applies to other signals of
the SoftwareISP class, although I wouldn't expect it would affect the
setSensorControls signal. Stanislaw, could you provide more information
about which threads the push and get functions are called from ?
Everything should be called from the camera manager thread.

Looking at this more deeply, I think the outputBufferReady and
statsReady signals may be mishandled, as they seem to be emitted from
the soft ISP worker thread but not treated the same way as the
inputBufferReady signal. We shouldn't have to deal with it when
connecting the signals in the user, the SoftwareISP class should handle
thread crossing, and emit all its signals from the camera manager
thread. Milan, is this something you could address ?

> I thought they would be in the same thread as the CameraManager event
> loop...  Perhaps we could/should have an assertion that the thread is
> the same - otherwise - yes it would probably need a lock if there's a
> reader and a writer on both ends of the queue.
> 
> I'd double check the threading first.
> 
> > Also I'm not sure if similar change like in this patch
> > is not needed for rpi DelayedControls
> 
> Probably. There's very little different between the two implementations,
> so we should probably keep them aligned with bugfixes at least until
> someone tries to realign them both again.

Naush, could you check this ?

> It looks like the cookie feature was easier to fork than to add, I can't
> remember all the details ;_(
> 
> 
> > Alternative fix would be to pre-fill ControlRingBuffer with
> > valid control values. Should we care about possibility
> > of queueCount_ overflowing ? 
> 
> I'm not sure what 'valid' control values would be ? I think just
> clamping to the most recent data is probably the best we can do ? And 'I
> think' would reflect the most up to date information we have about
> what's configured on the sensor - so I think it's still even the 'most
> correct' (and probably even 'is' correct) data we can return in the
> get() call in this event.
> 
> 
> I think I can already throw this on here, it seems like a sane input
> parameter validation:
> 
> 
> Reviewed-by: Kieran Bingham <kieran.bingham at ideasonboard.com>
> 
> >  src/libcamera/delayed_controls.cpp | 2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> > 
> > diff --git a/src/libcamera/delayed_controls.cpp b/src/libcamera/delayed_controls.cpp
> > index 94d0a575..78b0b8f7 100644
> > --- a/src/libcamera/delayed_controls.cpp
> > +++ b/src/libcamera/delayed_controls.cpp
> > @@ -202,7 +202,7 @@ bool DelayedControls::push(const ControlList &controls)
> >   */
> >  ControlList DelayedControls::get(uint32_t sequence)
> >  {
> > -       unsigned int index = std::max<int>(0, sequence - maxDelay_);
> > +       unsigned int index = std::clamp<int>(sequence - maxDelay_, 0, queueCount_ - 1);
> > 
> >         ControlList out(device_->controls());
> >         for (const auto &ctrl : values_) {

-- 
Regards,

Laurent Pinchart


More information about the libcamera-devel mailing list