[libcamera-devel,v1,3/3] libcamerasrc: Fix deadlock on EOS
diff mbox series

Message ID 20210825211852.1207168-4-nicolas@ndufresne.ca
State Accepted
Headers show
Series
  • Fix Gnome Cheese and multiple camera
Related show

Commit Message

Nicolas Dufresne Aug. 25, 2021, 9:18 p.m. UTC
From: Nicolas Dufresne <nicolas.dufresne@collabora.com>

It's not allowed in GStreamer to push events while holding the object
lock. This reduce the scope into which we hold the object lock. In
fact we don't need to protect against gst_task_resume() concurrency
when we stop the task as resume only do something if the task is paused.

This fixes a deadlock when running multiple instances of libcamerasrc
and closing one of the streaming window.

Signed-off-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
---
 src/gstreamer/gstlibcamerasrc.cpp | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

Comments

Laurent Pinchart Aug. 25, 2021, 11:02 p.m. UTC | #1
Hi Nicolas,

Thank you for the patch.

On Wed, Aug 25, 2021 at 05:18:52PM -0400, Nicolas Dufresne wrote:
> From: Nicolas Dufresne <nicolas.dufresne@collabora.com>
> 
> It's not allowed in GStreamer to push events while holding the object
> lock. This reduce the scope into which we hold the object lock. In
> fact we don't need to protect against gst_task_resume() concurrency
> when we stop the task as resume only do something if the task is paused.

I've tried to check this, but overall I'll trust you on that as my
knowledge is limited here.

> This fixes a deadlock when running multiple instances of libcamerasrc
> and closing one of the streaming window.
> 
> Signed-off-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>

Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

> ---
>  src/gstreamer/gstlibcamerasrc.cpp | 12 ++++++------
>  1 file changed, 6 insertions(+), 6 deletions(-)
> 
> diff --git a/src/gstreamer/gstlibcamerasrc.cpp b/src/gstreamer/gstlibcamerasrc.cpp
> index bdd9f88c..2be44edd 100644
> --- a/src/gstreamer/gstlibcamerasrc.cpp
> +++ b/src/gstreamer/gstlibcamerasrc.cpp
> @@ -312,12 +312,6 @@ gst_libcamera_src_task_run(gpointer user_data)
>  	}
>  
>  	{
> -		/*
> -		 * Here we need to decide if we want to pause or stop the task. This
> -		 * needs to happen in lock step with the callback thread which may want
> -		 * to resume the task.
> -		 */
> -		GLibLocker lock(GST_OBJECT(self));
>  		if (ret != GST_FLOW_OK) {
>  			if (ret == GST_FLOW_EOS) {
>  				g_autoptr(GstEvent) eos = gst_event_new_eos();
> @@ -332,6 +326,12 @@ gst_libcamera_src_task_run(gpointer user_data)
>  			return;
>  		}
>  
> +		/*
> +		 * Here we need to decide if we want to pause. This needs to
> +		 * happen in lock step with the callback thread which may want
> +		 * to resume the task and might push pending buffers.
> +		 */
> +		GLibLocker lock(GST_OBJECT(self));
>  		bool do_pause = true;
>  		for (GstPad *srcpad : state->srcpads_) {
>  			if (gst_libcamera_pad_has_pending(srcpad)) {

Patch
diff mbox series

diff --git a/src/gstreamer/gstlibcamerasrc.cpp b/src/gstreamer/gstlibcamerasrc.cpp
index bdd9f88c..2be44edd 100644
--- a/src/gstreamer/gstlibcamerasrc.cpp
+++ b/src/gstreamer/gstlibcamerasrc.cpp
@@ -312,12 +312,6 @@  gst_libcamera_src_task_run(gpointer user_data)
 	}
 
 	{
-		/*
-		 * Here we need to decide if we want to pause or stop the task. This
-		 * needs to happen in lock step with the callback thread which may want
-		 * to resume the task.
-		 */
-		GLibLocker lock(GST_OBJECT(self));
 		if (ret != GST_FLOW_OK) {
 			if (ret == GST_FLOW_EOS) {
 				g_autoptr(GstEvent) eos = gst_event_new_eos();
@@ -332,6 +326,12 @@  gst_libcamera_src_task_run(gpointer user_data)
 			return;
 		}
 
+		/*
+		 * Here we need to decide if we want to pause. This needs to
+		 * happen in lock step with the callback thread which may want
+		 * to resume the task and might push pending buffers.
+		 */
+		GLibLocker lock(GST_OBJECT(self));
 		bool do_pause = true;
 		for (GstPad *srcpad : state->srcpads_) {
 			if (gst_libcamera_pad_has_pending(srcpad)) {