[libcamera-devel] [PATCH] qcam: Fix camera reference leak on hot-unplug

Umang Jain email at uajain.com
Mon Jul 27 22:20:40 CEST 2020


Hi again,

On 7/27/20 9:20 PM, Laurent Pinchart wrote:
> Hi Umang,
>
> On Mon, Jul 27, 2020 at 03:38:00PM +0000, Umang Jain wrote:
>> On 7/27/20 8:35 PM, Laurent Pinchart wrote:
>>> On Mon, Jul 27, 2020 at 12:32:59PM +0000, Umang Jain wrote:
>>>> If the currently streaming camera is hot-unplugged,
>>>> a camera reference was still held by MainWindow::camera_,
>>>> preventing it to be destructed, until qcam window is
>>>> closed. Plug the leak in the hot-unplug handler itself.
>>>>
>>>> Signed-off-by: Umang Jain <email at uajain.com>
>>> Reviewed-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
>>>
>>> Does this fix all the shared pointer refcount issues you've been chasing
>>> ?
>> The refcount issues are sorted here. I spent extensive time on it (both for hotplug
>> and un-plug refcount).
>>
>> However, the other issue I am chasing (earlier believed was caused by refcount issue)
>> is still present - which primarily deals with event loop and how event-notifiers are processed.
>>
>> I can still trigger ASSERT(iter != notifiers_.end()); in EventDispatcherPoll::processNotifiers(),
>> on hot-unplugging a currently streaming camera. This is probably due to the fact that, when
>> destroying a Camera object, it always destroys V4L2VideoDevice() - which in turn, "delete"s
>> two EventNotifiers in it's destructor() and then processNotifiers() isn't aware about the deletion
>> and still trying to find a EventNotifier with concerned pollfd and fails  :-(
> The issue is that the camera object is meant to be destroyed in the
> thread it belongs to, as explained in a previous e-mail (see [1]). Is
> that something you can try fixing, with the pointers in that e-mail, or
> would you like to discuss it further first ?
>
> [1] https://lists.libcamera.org/pipermail/libcamera-devel/2020-July/010951.html
hmm, I figured that I need to call the destructor via 
Object::invokeMethod() with
connection type ConnectionTypeQueued to ensure the destructor is called 
within
it's own thread. Something on the lines:

void Object::deleteLater()

{

this->invokeMethod(&(typeid(this).name()::customDeletorFunc), 
ConnectionTypeQueued);

}

and

void className::customDeletorFunc()
{

~className();

}

which obviously does not compile for me.


How would one go about calling a destructor(in this case Camera's) from 
it's one
of the parent class(i.e. Object)? I am very cloudy around the syntax 
formation for
this->invokeMethod() above. Any help is appreciated.

>
>>>> ---
>>>>    src/qcam/main_window.cpp | 2 ++
>>>>    1 file changed, 2 insertions(+)
>>>>
>>>> diff --git a/src/qcam/main_window.cpp b/src/qcam/main_window.cpp
>>>> index 7bc1360..c8298ec 100644
>>>> --- a/src/qcam/main_window.cpp
>>>> +++ b/src/qcam/main_window.cpp
>>>> @@ -587,6 +587,8 @@ void MainWindow::processHotplug(HotplugEvent *e)
>>>>    		/* Check if the currently-streaming camera is removed. */
>>>>    		if (camera == camera_.get()) {
>>>>    			toggleCapture(false);
>>>> +			camera_->release();
>>>> +			camera_.reset();
>>>>    			cameraCombo_->setCurrentIndex(0);
>>>>    		}
>>>>    


More information about the libcamera-devel mailing list