[libcamera-devel] [PATCH 1/4] libcamera: mediadevice: Fix graph parsing error handling
Jacopo Mondi
jacopo at jmondi.org
Wed Jan 2 10:15:23 CET 2019
Hi Laurent,
thanks for the patches
A bit late, as this has been pushed already, but for the record.
On Tue, Jan 01, 2019 at 11:23:25PM +0200, Laurent Pinchart wrote:
> Most errors recorded during graph parsing are logged but not propagated
> to the caller. Fix this and delete objects that are created but not
> successfully added to the graph to avoid memory leaks. As the error code
> returned from the addObject() and populate*() functions doesn't matter
> much, turn them into bool functions.
>
Thanks, originally addObject() had void return value, I then returned
and error code, but ignored it in the caller. Quite silly.
> Additionally, add a way to query whether the media graph was valid, and
> clear objects before populating the graph to avoid leaking them.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
> ---
> src/libcamera/include/media_device.h | 10 ++--
> src/libcamera/media_device.cpp | 75 +++++++++++++++++-----------
> 2 files changed, 53 insertions(+), 32 deletions(-)
>
> diff --git a/src/libcamera/include/media_device.h b/src/libcamera/include/media_device.h
> index bca7c9a19471..74a67c81398a 100644
> --- a/src/libcamera/include/media_device.h
> +++ b/src/libcamera/include/media_device.h
> @@ -28,6 +28,7 @@ public:
> void close();
>
> int populate();
> + bool valid() const { return valid_; }
>
> const std::string driver() const { return driver_; }
> const std::string devnode() const { return devnode_; }
> @@ -37,18 +38,19 @@ private:
> std::string driver_;
> std::string devnode_;
> int fd_;
> + bool valid_;
>
> std::map<unsigned int, MediaObject *> objects_;
> MediaObject *object(unsigned int id);
> - int addObject(MediaObject *obj);
> + bool addObject(MediaObject *obj);
> void clear();
>
> std::vector<MediaEntity *> entities_;
> MediaEntity *getEntityByName(const std::string &name);
>
> - void populateEntities(const struct media_v2_topology &topology);
> - int populatePads(const struct media_v2_topology &topology);
> - int populateLinks(const struct media_v2_topology &topology);
> + bool populateEntities(const struct media_v2_topology &topology);
> + bool populatePads(const struct media_v2_topology &topology);
> + bool populateLinks(const struct media_v2_topology &topology);
> };
>
> } /* namespace libcamera */
> diff --git a/src/libcamera/media_device.cpp b/src/libcamera/media_device.cpp
> index d9a5196ac28c..fd5a31746075 100644
> --- a/src/libcamera/media_device.cpp
> +++ b/src/libcamera/media_device.cpp
> @@ -56,7 +56,7 @@ namespace libcamera {
> * \param devnode The media device node path
> */
> MediaDevice::MediaDevice(const std::string &devnode)
> - : devnode_(devnode), fd_(-1)
> + : devnode_(devnode), fd_(-1), valid_(false)
> {
> }
>
> @@ -99,6 +99,7 @@ void MediaDevice::clear()
>
> objects_.clear();
> entities_.clear();
> + valid_ = false;
> }
>
> /**
> @@ -163,18 +164,18 @@ void MediaDevice::close()
> * Add a new object to the global objects pool and fail if the object
> * has already been registered.
> */
> -int MediaDevice::addObject(MediaObject *obj)
> +bool MediaDevice::addObject(MediaObject *obj)
> {
>
> if (objects_.find(obj->id()) != objects_.end()) {
> LOG(Error) << "Element with id " << obj->id()
> << " already enumerated.";
> - return -EEXIST;
> + return false;
> }
>
> objects_[obj->id()] = obj;
>
> - return 0;
> + return true;
> }
>
> /*
> @@ -201,7 +202,7 @@ MediaEntity *MediaDevice::getEntityByName(const std::string &name)
> return nullptr;
> }
>
> -int MediaDevice::populateLinks(const struct media_v2_topology &topology)
> +bool MediaDevice::populateLinks(const struct media_v2_topology &topology)
> {
> media_v2_link *mediaLinks = reinterpret_cast<media_v2_link *>
> (topology.ptr_links);
> @@ -222,7 +223,7 @@ int MediaDevice::populateLinks(const struct media_v2_topology &topology)
> if (!source) {
> LOG(Error) << "Failed to find pad with id: "
> << source_id;
> - return -ENODEV;
> + return false;
> }
>
> unsigned int sink_id = mediaLinks[i].sink_id;
> @@ -231,20 +232,23 @@ int MediaDevice::populateLinks(const struct media_v2_topology &topology)
> if (!sink) {
> LOG(Error) << "Failed to find pad with id: "
> << sink_id;
> - return -ENODEV;
> + return false;
> }
>
> MediaLink *link = new MediaLink(&mediaLinks[i], source, sink);
> + if (!addObject(link)) {
> + delete link;
> + return false;
> + }
> +
> source->addLink(link);
> sink->addLink(link);
> -
> - addObject(link);
> }
>
> - return 0;
> + return true;
> }
>
> -int MediaDevice::populatePads(const struct media_v2_topology &topology)
> +bool MediaDevice::populatePads(const struct media_v2_topology &topology)
> {
> media_v2_pad *mediaPads = reinterpret_cast<media_v2_pad *>
> (topology.ptr_pads);
> @@ -258,16 +262,19 @@ int MediaDevice::populatePads(const struct media_v2_topology &topology)
> if (!mediaEntity) {
> LOG(Error) << "Failed to find entity with id: "
> << entity_id;
> - return -ENODEV;
> + return false;
> }
>
> MediaPad *pad = new MediaPad(&mediaPads[i], mediaEntity);
> - mediaEntity->addPad(pad);
> + if (!addObject(pad)) {
> + delete pad;
> + return false;
> + }
>
> - addObject(pad);
> + mediaEntity->addPad(pad);
> }
>
> - return 0;
> + return true;
> }
>
> /*
> @@ -275,17 +282,22 @@ int MediaDevice::populatePads(const struct media_v2_topology &topology)
> * reference in the MediaObject global pool and in the global vector of
> * entities.
> */
> -void MediaDevice::populateEntities(const struct media_v2_topology &topology)
> +bool MediaDevice::populateEntities(const struct media_v2_topology &topology)
> {
> media_v2_entity *mediaEntities = reinterpret_cast<media_v2_entity *>
> (topology.ptr_entities);
>
> for (unsigned int i = 0; i < topology.num_entities; ++i) {
> MediaEntity *entity = new MediaEntity(&mediaEntities[i]);
> + if (!addObject(entity)) {
> + delete entity;
> + return false;
> + }
>
> - addObject(entity);
> entities_.push_back(entity);
> }
> +
> + return true;
> }
>
> /**
> @@ -311,6 +323,8 @@ int MediaDevice::populate()
> __u64 version = -1;
> int ret;
>
> + clear();
> +
> /*
> * Keep calling G_TOPOLOGY until the version number stays stable.
> */
> @@ -343,24 +357,29 @@ int MediaDevice::populate()
> }
>
> /* Populate entities, pads and links. */
> - populateEntities(topology);
> -
> - ret = populatePads(topology);
> - if (ret)
> - goto error_free_objs;
> -
> - ret = populateLinks(topology);
> -error_free_objs:
> - if (ret)
> - clear();
> + if (populateEntities(topology) &&
> + populatePads(topology) &&
> + populateLinks(topology))
> + valid_ = true;
>
> delete[] links;
> delete[] ents;
> delete[] pads;
>
> - return ret;
> + if (!valid_) {
> + clear();
> + return -EINVAL;
> + }
}
>
> +/**
> + * \fn MediaDevice::valid()
> + * \brief Query whether the media graph is valid
\brief Query whether the media graph has been populated and is valid
I feel the useful information here is that the graph is populated and
its media objects can be accessed. I would convey that in documenting
the method.
Thanks
j
> + * \return true if the media graph is valid, false otherwise
> + */
> +
> /**
> * \var MediaDevice::objects_
> * \brief Global map of media objects (entities, pads, links) keyed by their
> --
> Regards,
>
> Laurent Pinchart
>
> _______________________________________________
> libcamera-devel mailing list
> libcamera-devel at lists.libcamera.org
> https://lists.libcamera.org/listinfo/libcamera-devel
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <https://lists.libcamera.org/pipermail/libcamera-devel/attachments/20190102/cb436acf/attachment-0001.sig>
More information about the libcamera-devel
mailing list