[{"id":5194,"web_url":"https://patchwork.libcamera.org/comment/5194/","msgid":"<20200612104927.GJ5957@pendragon.ideasonboard.com>","date":"2020-06-12T10:49:27","subject":"Re: [libcamera-devel] [PATCH v4 4/6] libcamera: camera_manager:\n\tIntroduce signals when a camera is added/removed","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"Hi Umang,\n\nThank you for the patch.\n\nOn Thu, Jun 11, 2020 at 05:16:07PM +0000, Umang Jain wrote:\n> Emit 'cameraAdded' and 'cameraRemoved' from CameraManager to enable\n> hotplug and hot-unplug support in application like QCam.\n> \n> To avoid use-after-free race between the CameraManager and the\n> application, emit the 'cameraRemoved' with the shared_ptr version\n> of <Camera *>. This requires to change the function signature of\n> CameraManager::removeCamera() API.\n> \n> Also, until now, CameraManager::Private::addCamera() transfers the\n> entire ownership of camera shared_ptr to CameraManager using std::move().\n> This patch changes the signature of Private::addCamera to accept pass-by-value\n> camera parameter. It is done to make it clear from the caller point of view\n> that the pointer within the caller will still be valid after this function\n> returns. With this change in, we can emit the camera pointer via 'cameraAdded'\n> signal without hitting a segfault.\n\nNice description, thanks. If you reflowed it to 72 columns as per the\nnormal git commit message policy, it would be perfect ;-)\n\n> Signed-off-by: Umang Jain <email@uajain.com>\n> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> ---\n>  include/libcamera/camera_manager.h |  6 ++++-\n>  src/libcamera/camera_manager.cpp   | 38 ++++++++++++++++++++++++++----\n>  src/libcamera/pipeline_handler.cpp |  2 +-\n>  3 files changed, 40 insertions(+), 6 deletions(-)\n> \n> diff --git a/include/libcamera/camera_manager.h b/include/libcamera/camera_manager.h\n> index 95dc636..9eb2b6f 100644\n> --- a/include/libcamera/camera_manager.h\n> +++ b/include/libcamera/camera_manager.h\n> @@ -13,6 +13,7 @@\n>  #include <vector>\n>  \n>  #include <libcamera/object.h>\n> +#include <libcamera/signal.h>\n>  \n>  namespace libcamera {\n>  \n> @@ -36,13 +37,16 @@ public:\n>  \n>  \tvoid addCamera(std::shared_ptr<Camera> camera,\n>  \t\t       const std::vector<dev_t> &devnums);\n> -\tvoid removeCamera(Camera *camera);\n> +\tvoid removeCamera(std::shared_ptr<Camera> camera);\n>  \n>  \tstatic const std::string &version() { return version_; }\n>  \n>  \tvoid setEventDispatcher(std::unique_ptr<EventDispatcher> dispatcher);\n>  \tEventDispatcher *eventDispatcher();\n>  \n> +\tSignal<std::shared_ptr<Camera>> cameraAdded;\n> +\tSignal<std::shared_ptr<Camera>> cameraRemoved;\n> +\n>  private:\n>  \tstatic const std::string version_;\n>  \tstatic CameraManager *self_;\n> diff --git a/src/libcamera/camera_manager.cpp b/src/libcamera/camera_manager.cpp\n> index 17a4afb..7f846c0 100644\n> --- a/src/libcamera/camera_manager.cpp\n> +++ b/src/libcamera/camera_manager.cpp\n> @@ -36,7 +36,7 @@ public:\n>  \tPrivate(CameraManager *cm);\n>  \n>  \tint start();\n> -\tvoid addCamera(std::shared_ptr<Camera> &camera,\n> +\tvoid addCamera(std::shared_ptr<Camera> camera,\n>  \t\t       const std::vector<dev_t> &devnums);\n>  \tvoid removeCamera(Camera *camera);\n>  \n> @@ -172,7 +172,7 @@ void CameraManager::Private::cleanup()\n>  \tenumerator_.reset(nullptr);\n>  }\n>  \n> -void CameraManager::Private::addCamera(std::shared_ptr<Camera> &camera,\n> +void CameraManager::Private::addCamera(std::shared_ptr<Camera> camera,\n>  \t\t\t\t       const std::vector<dev_t> &devnums)\n>  {\n>  \tMutexLocker locker(mutex_);\n> @@ -375,6 +375,34 @@ std::shared_ptr<Camera> CameraManager::get(dev_t devnum)\n>  \treturn iter->second.lock();\n>  }\n>  \n> +/**\n> + * \\var CameraManager::cameraAdded\n> + * \\brief Notify of a new camera added to the system\n> + *\n> + * This signal is emitted when a new camera is detected and successfully handled\n> + * by the camera manager. The notification occurs alike for cameras detected\n> + * when the manager is started with start() or when new cameras are later\n> + * connected to the system. When the signal is emitted the new camera is already\n> + * available from the list of cameras().\n> + *\n> + * The signal is emitted from the CameraManager thread. Applications shall\n> + * minimize the time spent in the signal handler and shall in particular not\n> + * perform any blocking operation.\n> + */\n> +\n> +/**\n> + * \\var CameraManager::cameraRemoved\n> + * \\brief Notify of a new camera removed from the system\n> + *\n> + * This signal is emitted when a camera is removed from the system. When the\n> + * signal is emitted the camera is not available from the list of cameras()\n> + * anymore.\n> + *\n> + * The signal is emitted from the CameraManager thread. Applications shall\n> + * minimize the time spent in the signal handler and shall in particular not\n> + * perform any blocking operation.\n> + */\n> +\n>  /**\n>   * \\brief Add a camera to the camera manager\n>   * \\param[in] camera The camera to be added\n> @@ -395,6 +423,7 @@ void CameraManager::addCamera(std::shared_ptr<Camera> camera,\n>  \tASSERT(Thread::current() == p_.get());\n>  \n>  \tp_->addCamera(camera, devnums);\n> +\tcameraAdded.emit(camera);\n>  }\n>  \n>  /**\n> @@ -407,11 +436,12 @@ void CameraManager::addCamera(std::shared_ptr<Camera> camera,\n>   *\n>   * \\context This function shall be called from the CameraManager thread.\n>   */\n> -void CameraManager::removeCamera(Camera *camera)\n> +void CameraManager::removeCamera(std::shared_ptr<Camera> camera)\n>  {\n>  \tASSERT(Thread::current() == p_.get());\n>  \n> -\tp_->removeCamera(camera);\n> +\tp_->removeCamera(camera.get());\n> +\tcameraRemoved.emit(camera);\n>  }\n>  \n>  /**\n> diff --git a/src/libcamera/pipeline_handler.cpp b/src/libcamera/pipeline_handler.cpp\n> index a0f6b0f..bad79dc 100644\n> --- a/src/libcamera/pipeline_handler.cpp\n> +++ b/src/libcamera/pipeline_handler.cpp\n> @@ -565,7 +565,7 @@ void PipelineHandler::disconnect()\n>  \t\t\tcontinue;\n>  \n>  \t\tcamera->disconnect();\n> -\t\tmanager_->removeCamera(camera.get());\n> +\t\tmanager_->removeCamera(camera);\n>  \t}\n>  \n>  \tcameras_.clear();","headers":{"Return-Path":"<laurent.pinchart@ideasonboard.com>","Received":["from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 94D9660C4E\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 12 Jun 2020 12:49:48 +0200 (CEST)","from pendragon.ideasonboard.com (81-175-216-236.bb.dnainternet.fi\n\t[81.175.216.236])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 0D15924F;\n\tFri, 12 Jun 2020 12:49:47 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key; \n\tunprotected) header.d=ideasonboard.com\n\theader.i=@ideasonboard.com\n\theader.b=\"YiikdufR\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1591958988;\n\tbh=qzo8QPvJ0X+PygrpKZqLPsDDC2eZ3fFY8ht3WW+oPww=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=YiikdufRY1qZBDWAxuiqNdsiSx1syUBXBscczL2LIt76G1JvgJ9Y0waDr+EeZKvO/\n\tRpdwqeCgb39KTbt6+cpCyZbuK38EfuoxVcN3omtHEnBx0UYPSAMA8qAvzqCdWEBxUb\n\t+oz+WK6mstR2pW/m9uHi2PLCHZed7jLB2Sw0yKDY=","Date":"Fri, 12 Jun 2020 13:49:27 +0300","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"Umang Jain <email@uajain.com>","Cc":"libcamera-devel@lists.libcamera.org","Message-ID":"<20200612104927.GJ5957@pendragon.ideasonboard.com>","References":"<20200611171528.9381-1-email@uajain.com>\n\t<20200611171528.9381-5-email@uajain.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<20200611171528.9381-5-email@uajain.com>","Subject":"Re: [libcamera-devel] [PATCH v4 4/6] libcamera: camera_manager:\n\tIntroduce signals when a camera is added/removed","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","X-List-Received-Date":"Fri, 12 Jun 2020 10:49:48 -0000"}}]