[libcamera-devel] [PATCH v2] cam: event_loop: Stop processing calls when event loop is exiting
Sebastian Fricke
sebastian.fricke at posteo.net
Wed Jan 20 11:29:21 CET 2021
Hey Niklas & Laurent,
On 20.01.2021 10:12, Niklas Söderlund wrote:
>Hi Laurent,
>
>Thanks for your feedback.
>
>On 2021-01-20 05:56:46 +0200, Laurent Pinchart wrote:
>> Ni Niklas,
>>
>> Thank you for the patch.
>>
>> On Wed, Jan 20, 2021 at 12:33:15AM +0100, Niklas Söderlund wrote:
>> > Terminating the event loop with EventLoop::exit() does not grantee that
>> > it will terminate. If the event loops 'call later' queue can be kept
>> > non-empty by continuously queuing new calls using EventLoop::callLater()
>> > either from a different thread or from callbacks in the loop itself
>> > EventLoop::dispatchCalls() will never complete and the loop will run
>> > forever.
>> >
>> > Solve this by evaluating the exit condition between each callback and
>> > only enter the idle loop if there are no callbacks to process.
>> >
>> > Reported-by: Sebastian Fricke <sebastian.fricke at posteo.net>
>> > Fixes: f49e93338b6309a6 ("cam: event_loop: Add deferred calls support")
>> > Signed-off-by: Niklas Söderlund <niklas.soderlund at ragnatech.se>
>>
>> This seems to be even more of a hack than the previous version :-( Can
>> we fix this properly please ?
>
>I would like noting more then to fix this properly.
>
>The heart of the problem is that some of our pipelines require more then
>N requests to be queued for it to complete N. I agree it's bad that our
>pipelines behaves differently and something should be done to align
>them.
>
>It feels natural that such work would be paired with a compliance tool
>so situations like this can be detected early and avoided. I have been
>tempted many times to start a compliance tool but have postponed it. My
I am currently looking for a follow up project to start within the next 2-3
weeks. If you would like to we could talk about your idea and design, so
that I am able to start working on it, as soon as my current projects
are finished.
>primary reason for doing so is that we never really defined the number
>of requests queued vs. pipeline depth and pipeline stalls and what a
>correct behavior in such situations is. I was pleased with the camera
>model work had was hoping it would lead to a more strict definition wich
>such tools could be built upon.
>
>How ever solving the core problem is a rather large task to sort out.
If I understood your discussion correctly, then the sub-tasks of this
one 'bigger' task are:
- Make sure that each pipeline requies exactly the expected amount of
requests in order process the given amount of frames, by implementing
a complience tool to check the pipelines.
- Switch the behavior of the `cam` command to count the number of queued
requests to the camera instead of the number of completed requests.
Which other tasks would you add to that list?
>How can we handle the issue in the short time frame? No matter how I
>dice it I see a hack in cam is needed ;-(
>
>- The best option I see is to use the 'process call in batches' solution
> as your suggestion in v1 and then either remove support for
> --capture=N or accept that on "broken" pipelines N+pipeline depth
> frames will be processed, but at least cam won't deadlock.
>
>- Another other option (that I really don't like) is to revert the
> deferred calls support.
>
>- We can also fix this properly in cam by only queuing N requests and
> expecting N requests to complete. This will break --capture=N on some
> pipelines, but perhaps that is the pressure we need to push the fix
> upwards.
I think I like the idea of starting out with the right behavior in the
first place. Are there any cases known to you guys, where the `cam`
application is used for anything else than testing the libcamera project?
Like is there anything that could actually "break"?
>
>>
>> > ---
>> > * Changes since v1
>> > - Was [PATCH 0/2] cam: Fix races in event loop and long request
>> > processing times
>> > - Rework dispatchCalls() instead of callLater() for a simpler fix.
>> > ---
>> > src/cam/event_loop.cpp | 22 +++++++++++++---------
>> > src/cam/event_loop.h | 2 +-
>> > 2 files changed, 14 insertions(+), 10 deletions(-)
>> >
>> > diff --git a/src/cam/event_loop.cpp b/src/cam/event_loop.cpp
>> > index 94c5d1d362455f33..18786b4500be9b6f 100644
>> > --- a/src/cam/event_loop.cpp
>> > +++ b/src/cam/event_loop.cpp
>> > @@ -41,7 +41,9 @@ int EventLoop::exec()
>> > exit_.store(false, std::memory_order_release);
>> >
>> > while (!exit_.load(std::memory_order_acquire)) {
>> > - dispatchCalls();
>> > + if (dispatchCall())
>> > + continue;
>> > +
>> > event_base_loop(event_, EVLOOP_NO_EXIT_ON_EMPTY);
>> > }
>> >
>> > @@ -70,17 +72,19 @@ void EventLoop::callLater(const std::function<void()> &func)
>> > interrupt();
>> > }
>> >
>> > -void EventLoop::dispatchCalls()
>> > +bool EventLoop::dispatchCall()
>> > {
>> > std::unique_lock<std::mutex> locker(lock_);
>> >
>> > - for (auto iter = calls_.begin(); iter != calls_.end(); ) {
>> > - std::function<void()> call = std::move(*iter);
>> > + if (calls_.empty())
>> > + return false;
>> >
>> > - iter = calls_.erase(iter);
>> > + auto iter = calls_.begin();
>> > + std::function<void()> call = std::move(*iter);
>> > + calls_.erase(iter);
>> >
>> > - locker.unlock();
>> > - call();
>> > - locker.lock();
>> > - }
>> > + locker.unlock();
>> > + call();
>> > +
>> > + return true;
>> > }
>> > diff --git a/src/cam/event_loop.h b/src/cam/event_loop.h
>> > index 408073c50594d09d..b84e1c9e432086e3 100644
>> > --- a/src/cam/event_loop.h
>> > +++ b/src/cam/event_loop.h
>> > @@ -38,7 +38,7 @@ private:
>> > std::mutex lock_;
>> >
>> > void interrupt();
>> > - void dispatchCalls();
>> > + bool dispatchCall();
>> > };
>> >
>> > #endif /* __CAM_EVENT_LOOP_H__ */
>>
>> --
>> Regards,
>>
>> Laurent Pinchart
>
>--
>Regards,
>Niklas Söderlund
Greetings,
Sebastian Fricke
>_______________________________________________
>libcamera-devel mailing list
>libcamera-devel at lists.libcamera.org
>https://lists.libcamera.org/listinfo/libcamera-devel
More information about the libcamera-devel
mailing list