[libcamera-devel] [RFC PATCH] android: CameraWorker: Cancel pending messages in queue in stop()
Laurent Pinchart
laurent.pinchart at ideasonboard.com
Fri May 21 15:30:42 CEST 2021
Hello,
On Fri, May 21, 2021 at 01:44:44PM +0900, Hirokazu Honda wrote:
> On Thu, May 20, 2021 at 8:12 PM Jacopo Mondi wrote:
> > On Fri, Apr 23, 2021 at 01:04:27PM +0900, Hirokazu Honda wrote:
> > > CameraWorker::stop() executes Thread::exit() and Thread::wait().
> > > However, intuitively, the two functions doesn't clean up pending
>
> s/intuitively/surprisingly/
>
> > messages in the message queue of the thread. They are rather
> > > cleaned in the destruction of CameraWorker, but CameraWorker's
> > > life time is the same as CameraDevice and thus CameraManager,
> > > which is never destroyed. On the other hand,
> > > Camera3RequestDescriptors are destroyed in CameraDevice::stop().
> > >
> > > This causes CameraWorker::Worker::queueRequest() starts to be
> > > executed after CameraWorker::start(), which is after
> >
> > I'm not sure I'm following right the sequence of Worker::queueRequest(),
> > CameraWorker::start() and CameraDevice::stop()
> >
> > Should this be CameraWorker::stop() ?
> >
> > Did you ever triggered this failure ?
>
> I have encountered this issue when I tested my flush().
> The HAL API flow is CameraDevice::close() ->
> (CameraDevice::configureStreams() ->) CameraDevice::processCaptureRequest().
> The internal flow is
> * in CameraDevice::close()
> - CameraWorker::stop()
> - Thread::exit()
> - Thread::wait()
> - Camera::stop()
> * in CameraDevice::processCaptureResult()
> - CameraWorker::start()
>
> As I said, after CameraWorker::stop(), pending requests remain in the queue.
> CameraWorker::start() starts with the remained requests and because the
> object of the requests are destroyed by clearing descriptors_, the SIGSEGV
> happens.
You're right. We can have messages in the queue when the thread is
stopped, and they're not removed. I won't say it's by design :-), but
thinking about it, forcing automatic dispatching of all messages when
the thread is stopped would prevent fast stop of threads, so I think it
shouldn't be done by default (or at least not without a way to prevent
it).
> > > CameraDevice::stop(). This obviously causes a segmentation fault,
> > > because CameraWorker::Worker::queueRequest() touches
> > > CaptureRequest which is owned by Camera3RequestDescriptor.
> > >
> > > This fixes the issue by cancel pending message in thread queue in
> > > CameraWorker::stop() with Thread::dispatchMessages().
> >
> > For my limited understanding of the Object and Thread classes, I think
> > it's ok to dispatch all pending method calls.
> >
> > However what concerns me is also Request that are pending in
> > void CameraWorker::Worker::processRequest() when the Worker gets
> > stopped. Should we wait for the queue of pending requests to have
> > finised waiting their fences (or instrument an interruption mechanism)
> > before returning from stop() ?
>
> If I understand correctly, Thread::dispatchMessages() executes
> CameraWorker::Worker::processRequest().
> Thread::dispatchMessages() calls Object::message(), and it executes
> InvokeMessage::invoke().
> I am honestly unsure.
> Laurent should know as Laurent is the original author
> of Thread::dispatchMessages().
>
> > > Signed-off-by: Hirokazu Honda <hiroh at chromium.org>
> > > ---
> > > src/android/camera_worker.cpp | 1 +
> > > 1 file changed, 1 insertion(+)
> > >
> > > diff --git a/src/android/camera_worker.cpp b/src/android/camera_worker.cpp
> > > index 300ddde0..b68ce9d5 100644
> > > --- a/src/android/camera_worker.cpp
> > > +++ b/src/android/camera_worker.cpp
> > > @@ -62,6 +62,7 @@ void CameraWorker::start()
> > >
> > > void CameraWorker::stop()
> > > {
> > > + thread_.dispatchMessages(Message::Type::InvokeMessage);
Thread::dispatchMessages() is meant to be called from within the thread
only. This isn't documented, I'll send a patch for that.
One option here to call dispatchMessage() from the thread would be the
following (untested):
diff --git a/src/android/camera_worker.cpp b/src/android/camera_worker.cpp
index 300ddde03645..9f727826e23f 100644
--- a/src/android/camera_worker.cpp
+++ b/src/android/camera_worker.cpp
@@ -52,18 +52,24 @@ void CaptureRequest::queue()
*/
CameraWorker::CameraWorker()
{
- worker_.moveToThread(&thread_);
+ worker_.moveToThread(this);
}
void CameraWorker::start()
{
- thread_.start();
+ Thread::start();
}
void CameraWorker::stop()
{
- thread_.exit();
- thread_.wait();
+ exit();
+ wait();
+}
+
+void CameraWorker::run()
+{
+ exec();
+ dispatchMessages(Message::Type::InvokeMessage);
}
void CameraWorker::queueRequest(CaptureRequest *request)
diff --git a/src/android/camera_worker.h b/src/android/camera_worker.h
index 64b1658b61b4..e289ef9b8655 100644
--- a/src/android/camera_worker.h
+++ b/src/android/camera_worker.h
@@ -42,7 +42,7 @@ private:
std::unique_ptr<libcamera::Request> request_;
};
-class CameraWorker
+class CameraWorker : private libcamera::Thread
{
public:
CameraWorker();
@@ -52,6 +52,9 @@ public:
void queueRequest(CaptureRequest *request);
+protected:
+ void run() override;
+
private:
class Worker : public libcamera::Object
{
@@ -63,7 +66,6 @@ private:
};
Worker worker_;
- libcamera::Thread thread_;
};
#endif /* __ANDROID_CAMERA_WORKER_H__ */
Could you test this to see if it fixes your issue ?
I'm also considering deleting all posted messages when the thread is
stopped, as I really can't see a use case for keeping messages to be
processed when the thread is restarted. Does anyone have an opinion ?
I'll likely post a patch as an RFC.
> > > thread_.exit();
> > > thread_.wait();
> > > }
--
Regards,
Laurent Pinchart
More information about the libcamera-devel
mailing list