[libcamera-devel] [PATCH] lc-compliance: simple_capture: Free Requests properly
Kieran Bingham
kieran.bingham at ideasonboard.com
Wed Nov 30 12:35:12 CET 2022
Quoting Paul Elder (2022-11-30 11:27:40)
> On Tue, Nov 29, 2022 at 05:39:16PM +0000, Kieran Bingham wrote:
> > Quoting Paul Elder via libcamera-devel (2022-11-29 11:00:05)
> > > In the simple capture tests, in the capture functions, the Requests were
> > > auto-deallocated by the function going out of scope after the test
> > > completed. However, before the end of the scope, the Framebuffers that
> > > the Requests referred to were manually freed. Thus when the Requests
> > > were deallocated, they tried to cancel their Framebuffers, which involve
> > > setting the status to cancelled, which obviously causes a segfault
> > > because the Framebuffers had already been freed.
> >
> > This worries me that we have a path that could let application cause a
> > segfault in libcamera. That's not good.
>
> That's true.
>
> Should we fix this instead in Request then? By checking that
> FramBuffer::_d() == nullptr in Request::Private::doCancelRequest() like
> rsglobal does in the github issue [1]?
As this is clearly a situation that applciations could get themselves into -
perhaps we need to have 'something' but with a clear message to tellng
them they've messed up ?
> [1] https://github.com/kbingham/libcamera/issues/60#issue-1450103563
>
> >
> > > Fix this by moving the list of Requests to a member variable and
> > > deallocating them before deallocating the Framebuffers at stop() time.
> >
> > Fixing this here seems reasonable, but I'm concerned that we now need a
> > unit test in libcamera unit tests which ensure or validate the lifetimes
> > of freeing buffers/requests.
>
> Yeah that's true, this should probably be split into another compliance
> test in itself.
>
> >
> > If I understand it, that means that we have a lifetime management issue
> > still between the Request and the Buffer object that may be associated
> > with it.
> >
> > Bug: https://bugs.libcamera.org/show_bug.cgi?id=171
> > Reviewed-by: Kieran Bingham <kieran.bingham at ideasonboard.com>
> > Tested-by: Kieran Bingham <kieran.bingham at ideasonboard.com>
> >
> > But I am not sure we should consider the underlying issue resolved yet.
> > I feel like the crash in lc-compliance is simply telling us we have a
> > fault with our API.
> >
> > The question is if we should still fix lc-compliance here or not - or if
> > we should keep it 'broken' so that we can validate whatever fix we do
> > internally in libcamera?
>
> I think split this specific issue into a separate smaller test. I
> don't think there's a need to test this specific issue in all
> combinations that we test currently in the simple capture test.
Absolutely. It's just about figuring out what the applications could be
likely to get wrong, and if /we've/ got it wrong ... then I guess
applications could.
--
Kieran
>
>
> Thanks,
>
> Paul
>
> >
> >
> > > Signed-off-by: Paul Elder <paul.elder at ideasonboard.com>
> > > ---
> > > src/apps/lc-compliance/simple_capture.cpp | 7 +++----
> > > src/apps/lc-compliance/simple_capture.h | 1 +
> > > 2 files changed, 4 insertions(+), 4 deletions(-)
> > >
> > > diff --git a/src/apps/lc-compliance/simple_capture.cpp b/src/apps/lc-compliance/simple_capture.cpp
> > > index ab5cb35c..cf4d7cf3 100644
> > > --- a/src/apps/lc-compliance/simple_capture.cpp
> > > +++ b/src/apps/lc-compliance/simple_capture.cpp
> > > @@ -65,6 +65,7 @@ void SimpleCapture::stop()
> > > camera_->requestCompleted.disconnect(this);
> > >
> > > Stream *stream = config_->at(0).stream();
> > > + requests_.clear();
> > > allocator_->free(stream);
> > > }
> > >
> > > @@ -95,7 +96,6 @@ void SimpleCaptureBalanced::capture(unsigned int numRequests)
> > > captureLimit_ = numRequests;
> > >
> > > /* Queue the recommended number of reqeuests. */
> > > - std::vector<std::unique_ptr<libcamera::Request>> requests;
> > > for (const std::unique_ptr<FrameBuffer> &buffer : buffers) {
> > > std::unique_ptr<Request> request = camera_->createRequest();
> > > ASSERT_TRUE(request) << "Can't create request";
> > > @@ -104,7 +104,7 @@ void SimpleCaptureBalanced::capture(unsigned int numRequests)
> > >
> > > ASSERT_EQ(queueRequest(request.get()), 0) << "Failed to queue request";
> > >
> > > - requests.push_back(std::move(request));
> > > + requests_.push_back(std::move(request));
> > > }
> > >
> > > /* Run capture session. */
> > > @@ -156,7 +156,6 @@ void SimpleCaptureUnbalanced::capture(unsigned int numRequests)
> > > captureLimit_ = numRequests;
> > >
> > > /* Queue the recommended number of reqeuests. */
> > > - std::vector<std::unique_ptr<libcamera::Request>> requests;
> > > for (const std::unique_ptr<FrameBuffer> &buffer : buffers) {
> > > std::unique_ptr<Request> request = camera_->createRequest();
> > > ASSERT_TRUE(request) << "Can't create request";
> > > @@ -165,7 +164,7 @@ void SimpleCaptureUnbalanced::capture(unsigned int numRequests)
> > >
> > > ASSERT_EQ(camera_->queueRequest(request.get()), 0) << "Failed to queue request";
> > >
> > > - requests.push_back(std::move(request));
> > > + requests_.push_back(std::move(request));
> > > }
> > >
> > > /* Run capture session. */
> > > diff --git a/src/apps/lc-compliance/simple_capture.h b/src/apps/lc-compliance/simple_capture.h
> > > index fd9d2a97..2911d601 100644
> > > --- a/src/apps/lc-compliance/simple_capture.h
> > > +++ b/src/apps/lc-compliance/simple_capture.h
> > > @@ -32,6 +32,7 @@ protected:
> > > std::shared_ptr<libcamera::Camera> camera_;
> > > std::unique_ptr<libcamera::FrameBufferAllocator> allocator_;
> > > std::unique_ptr<libcamera::CameraConfiguration> config_;
> > > + std::vector<std::unique_ptr<libcamera::Request>> requests_;
> > > };
> > >
> > > class SimpleCaptureBalanced : public SimpleCapture
> > > --
> > > 2.35.1
> > >
More information about the libcamera-devel
mailing list