summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/libcamera/camera_manager.cpp8
-rw-r--r--src/libcamera/pipeline_handler.cpp18
2 files changed, 17 insertions, 9 deletions
diff --git a/src/libcamera/camera_manager.cpp b/src/libcamera/camera_manager.cpp
index 576856ab..dbdc78e7 100644
--- a/src/libcamera/camera_manager.cpp
+++ b/src/libcamera/camera_manager.cpp
@@ -63,7 +63,6 @@ private:
bool initialized_;
int status_;
- std::vector<std::shared_ptr<PipelineHandler>> pipes_;
std::unique_ptr<DeviceEnumerator> enumerator_;
IPAManager ipaManager_;
@@ -144,7 +143,6 @@ int CameraManager::Private::init()
LOG(Camera, Debug)
<< "Pipeline handler \"" << factory->name()
<< "\" matched";
- pipes_.push_back(std::move(pipe));
}
}
@@ -158,11 +156,9 @@ void CameraManager::Private::cleanup()
/* TODO: unregister hot-plug callback here */
/*
- * Release all references to cameras and pipeline handlers to ensure
- * they all get destroyed before the device enumerator deletes the
- * media devices.
+ * Release all references to cameras to ensure they all get destroyed
+ * before the device enumerator deletes the media devices.
*/
- pipes_.clear();
cameras_.clear();
enumerator_.reset(nullptr);
diff --git a/src/libcamera/pipeline_handler.cpp b/src/libcamera/pipeline_handler.cpp
index a0f6b0f1..38c85779 100644
--- a/src/libcamera/pipeline_handler.cpp
+++ b/src/libcamera/pipeline_handler.cpp
@@ -559,7 +559,21 @@ void PipelineHandler::mediaDeviceDisconnected(MediaDevice *media)
*/
void PipelineHandler::disconnect()
{
- for (std::weak_ptr<Camera> ptr : cameras_) {
+ /*
+ * Each camera holds a reference to its associated pipeline handler
+ * instance. Hence, when the last camera is dropped, the pipeline
+ * handler will get destroyed by the last manager_->removeCamera(camera)
+ * call in the loop below.
+ *
+ * This is acceptable as long as we make sure that the code path does not
+ * access any member of the (already destroyed) pipeline handler instance
+ * afterwards. Therefore, we move the cameras_ vector to a local temporary
+ * container to avoid accessing freed memory later i.e. to explicitly run
+ * cameras_.clear().
+ */
+ std::vector<std::weak_ptr<Camera>> cameras{ std::move(cameras_) };
+
+ for (std::weak_ptr<Camera> ptr : cameras) {
std::shared_ptr<Camera> camera = ptr.lock();
if (!camera)
continue;
@@ -567,8 +581,6 @@ void PipelineHandler::disconnect()
camera->disconnect();
manager_->removeCamera(camera.get());
}
-
- cameras_.clear();
}
/**