<div dir="ltr"><div dir="ltr"><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Fri, 28 Oct 2022 at 11:24, Kieran Bingham <<a href="mailto:kieran.bingham@ideasonboard.com">kieran.bingham@ideasonboard.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Quoting Naushir Patuck via libcamera-devel (2022-10-28 10:42:55)<br>
> Hi all,<br>
> <br>
> I wonder if I could get some thoughts regarding a problem we are seeing<br>
> with running multiple cameras in separate libcamera processes on Raspberry<br>
> Pi (this probably affects any/all platforms though).<br>
> <br>
> In my scenario, I have libcamera process 1 running "cam -c 1 -C" and<br>
> streaming from imx477 using the Raspberry Pi pipeline handler.  In process<br>
> 2, I have "cam -c 2 -C" running streaming from a USB camera using the<br>
> uvcvideo pipeline handler.  If I exit process 2, I get the following error<br>
> messages:<br>
> <br>
> [0:01:33.155169911] [1392] ERROR V4L2 v4l2_videodevice.cpp:1241<br>
> /dev/video2[16:cap]: Unable to request 0 buffers: Device or resource busy<br>
> [0:01:33.155359910] [1392] ERROR V4L2 v4l2_videodevice.cpp:1241<br>
> /dev/video3[17:cap]: Unable to request 0 buffers: Device or resource busy<br>
> [0:01:33.155460595] [1392] ERROR V4L2 v4l2_videodevice.cpp:1241<br>
> /dev/video13[18:out]: Unable to request 0 buffers: Device or resource busy<br>
> [0:01:33.155564354] [1392] ERROR V4L2 v4l2_videodevice.cpp:1241<br>
> /dev/video14[19:cap]: Unable to request 0 buffers: Device or resource busy<br>
> [0:01:33.155664150] [1392] ERROR V4L2 v4l2_videodevice.cpp:1241<br>
> /dev/video15[20:cap]: Unable to request 0 buffers: Device or resource busy<br>
> [0:01:33.155763483] [1392] ERROR V4L2 v4l2_videodevice.cpp:1241<br>
> /dev/video16[21:cap]: Unable to request 0 buffers: Device or resource busy<br>
> <br>
> These errors come up because the V4L2VideoDevice destructor in process 2 is<br>
> indirectly calling ioctl(REQBUFS, 0) on all the Unicam and ISP device nodes<br>
> while the device driver buffer queues are actively owned and used by<br>
> process 1. This does not actively interfere with process 1 running, it<br>
> continues happily enough.<br>
> <br>
> The error here stems from the fact that the RPi pipeline handler<br>
> PipelineHandler::match() opens all the device nodes for every Camera object<br>
> registered through PipelineHandler::registerCamera().  So even if the<br>
> Camera was never used by a process, when terminating the V4L2VideoDevice<br>
> destructor will call ioctl(REQBUFS, 0) for every single device.  This<br>
> behavior is exactly the same for the ipu3 and rkisp1 pipeline handlers.<br>
> <br>
> So the question is how to fix this and avoid the error messages?<br>
> <br>
> 1) The V4L2VideoDevice destructor should not call ioctl(REQBUFS, 0) if it<br>
> has not allocated buffers for the device:<br>
> <br>
> diff --git a/src/libcamera/v4l2_videodevice.cpp<br>
> b/src/libcamera/v4l2_videodevice.cpp<br>
> index e30858c9fa02..108e60f035ab 100644<br>
> --- a/src/libcamera/v4l2_videodevice.cpp<br>
> +++ b/src/libcamera/v4l2_videodevice.cpp<br>
> @@ -758,7 +758,8 @@ void V4L2VideoDevice::close()<br>
>         if (!isOpen())<br>
>                 return;<br>
> <br>
> -       releaseBuffers();<br>
> +       if (cache_)<br>
> +               releaseBuffers();<br>
>         delete fdBufferNotifier_;<br>
> <br>
> 2) All pipeline handlers need to change and avoid calling device open() in<br>
> PipelineHandler::match(), and defer this call to when configure() gets<br>
> called.<br>
> <br>
> Option 2 is not trivial, as (at least in the RPi pipeline handler) a bunch<br>
> of validation occurs in PipelineHandler::match() that needs the device<br>
> nodes to be open. In my opinion, option 1 seems to be the correct thing to<br>
> do.<br>
> <br>
> Any other suggestions or thoughts?<br>
<br>
As a quick reply, without looking through code - then yes, opeion 1<br>
seems most reasonable. We should not be trying to release things that we<br>
haven't claimed in that process.<br>
<br>
At least the kernel is preventing it from actually releasing any memory<br>
- (I believe) - but indeed - it's not a good position to be in, trying<br>
to free someone elses buffers.<br></blockquote><div><br></div><div>The kernel handles this correctly, so nothing stops working thankfully!</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
I'd check that releaseBuffers() isn't called anywhere else explicitly (I<br>
expect this is just the destructor code path?) which might make the<br>
cache_ check better suited in releaseBuffers() itself ... but otherwise<br>
it seems sane to make sure we only release resources we acquire.<br></blockquote><div><br></div><div>releaseBuffers() only ever gets called from close(), but I'll put the</div><div>cache_ check in releaseBuffers() to be safe from possible future changes.</div><div><br></div><div>Naush</div><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
--<br>
Kieran<br>
<br>
<br>
<br>
> <br>
> Regards,<br>
> Naush<br>
</blockquote></div></div>