summaryrefslogtreecommitdiff
path: root/src/libcamera/pipeline_handler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libcamera/pipeline_handler.cpp')
-rw-r--r--src/libcamera/pipeline_handler.cpp18
1 files changed, 15 insertions, 3 deletions
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();
}
/**