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> pipes_; std::unique_ptr 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 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> cameras{ std::move(cameras_) }; + + for (std::weak_ptr ptr : cameras) { std::shared_ptr camera = ptr.lock(); if (!camera) continue; @@ -567,8 +581,6 @@ void PipelineHandler::disconnect() camera->disconnect(); manager_->removeCamera(camera.get()); } - - cameras_.clear(); } /**