libcamera: camera_manager: Do not emit signals while holding lock

Both `CameraManager::Private::{add,remove}Camera()` emit the
`camera{Added,Removed}` signals, respectively, while holding the
lock protecting the list of cameras.

This is problematic because if a callback tries to call `cameras()`,
then the same (non-recursive) lock would be locked again.

Furthermore, there is no real need to hold the lock while user code
is running, so release the lock as soon as possible.

Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
Reviewed-by: Harvey Yang <chenghaoyang@chromium.org>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
This commit is contained in:
Barnabás Pőcze 2025-02-06 15:59:42 +01:00
parent b3272f7827
commit d505bd5360

View file

@ -202,24 +202,24 @@ void CameraManager::Private::addCamera(std::shared_ptr<Camera> camera)
{ {
ASSERT(Thread::current() == this); ASSERT(Thread::current() == this);
MutexLocker locker(mutex_); {
MutexLocker locker(mutex_);
for (const std::shared_ptr<Camera> &c : cameras_) { for (const std::shared_ptr<Camera> &c : cameras_) {
if (c->id() == camera->id()) { if (c->id() == camera->id()) {
LOG(Camera, Fatal) LOG(Camera, Fatal)
<< "Trying to register a camera with a duplicated ID '" << "Trying to register a camera with a duplicated ID '"
<< camera->id() << "'"; << camera->id() << "'";
return; return;
}
} }
cameras_.push_back(camera);
} }
cameras_.push_back(std::move(camera));
unsigned int index = cameras_.size() - 1;
/* Report the addition to the public signal */ /* Report the addition to the public signal */
CameraManager *const o = LIBCAMERA_O_PTR(); CameraManager *const o = LIBCAMERA_O_PTR();
o->cameraAdded.emit(cameras_[index]); o->cameraAdded.emit(camera);
} }
/** /**
@ -236,20 +236,22 @@ void CameraManager::Private::removeCamera(std::shared_ptr<Camera> camera)
{ {
ASSERT(Thread::current() == this); ASSERT(Thread::current() == this);
MutexLocker locker(mutex_); {
MutexLocker locker(mutex_);
auto iter = std::find_if(cameras_.begin(), cameras_.end(), auto iter = std::find_if(cameras_.begin(), cameras_.end(),
[camera](std::shared_ptr<Camera> &c) { [camera](std::shared_ptr<Camera> &c) {
return c.get() == camera.get(); return c.get() == camera.get();
}); });
if (iter == cameras_.end()) if (iter == cameras_.end())
return; return;
cameras_.erase(iter);
}
LOG(Camera, Debug) LOG(Camera, Debug)
<< "Unregistering camera '" << camera->id() << "'"; << "Unregistering camera '" << camera->id() << "'";
cameras_.erase(iter);
/* Report the removal to the public signal */ /* Report the removal to the public signal */
CameraManager *const o = LIBCAMERA_O_PTR(); CameraManager *const o = LIBCAMERA_O_PTR();
o->cameraRemoved.emit(camera); o->cameraRemoved.emit(camera);