Show a patch.

GET /api/patches/118/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 118,
    "url": "https://patchwork.libcamera.org/api/patches/118/?format=api",
    "web_url": "https://patchwork.libcamera.org/patch/118/",
    "project": {
        "id": 1,
        "url": "https://patchwork.libcamera.org/api/projects/1/?format=api",
        "name": "libcamera",
        "link_name": "libcamera",
        "list_id": "libcamera_core",
        "list_email": "libcamera-devel@lists.libcamera.org",
        "web_url": "",
        "scm_url": "",
        "webscm_url": ""
    },
    "msgid": "<20190101212328.18361-1-laurent.pinchart@ideasonboard.com>",
    "date": "2019-01-01T21:23:25",
    "name": "[libcamera-devel,1/4] libcamera: mediadevice: Fix graph parsing error handling",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": false,
    "hash": "2a43a0d890c328220bfd721e79ba15b82e4ac68f",
    "submitter": {
        "id": 2,
        "url": "https://patchwork.libcamera.org/api/people/2/?format=api",
        "name": "Laurent Pinchart",
        "email": "laurent.pinchart@ideasonboard.com"
    },
    "delegate": null,
    "mbox": "https://patchwork.libcamera.org/patch/118/mbox/",
    "series": [
        {
            "id": 45,
            "url": "https://patchwork.libcamera.org/api/series/45/?format=api",
            "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=45",
            "date": "2019-01-01T21:23:26",
            "name": "[libcamera-devel,1/4] libcamera: mediadevice: Fix graph parsing error handling",
            "version": 1,
            "mbox": "https://patchwork.libcamera.org/series/45/mbox/"
        }
    ],
    "comments": "https://patchwork.libcamera.org/api/patches/118/comments/",
    "check": "pending",
    "checks": "https://patchwork.libcamera.org/api/patches/118/checks/",
    "tags": {},
    "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 9EB6F60B31\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue,  1 Jan 2019 22:22:33 +0100 (CET)",
            "from avalon.bb.dnainternet.fi\n\t(dfj612ybrt5fhg77mgycy-3.rev.dnainternet.fi\n\t[IPv6:2001:14ba:21f5:5b00:2e86:4862:ef6a:2804])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 8BA64505\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue,  1 Jan 2019 22:22:32 +0100 (CET)"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1546377752;\n\tbh=nfgdTWa8yY4Udqvliy/qVwhEXGhtZ3ngjvmQJv3xGSU=;\n\th=From:To:Subject:Date:From;\n\tb=mtUnx3Dm4lxqfIV5EwC18lI5f0zIpQvjEA7GQXEUgVsuDOi64bWIYXq6ao93iz05B\n\thlXQomqXZWdLg/43NKLpRMxTh7dN7AaOLRFmiZ/5MPHEq5hOxR5eH6LK0FbSfbMIHc\n\tVl680hRrr9oKZl29M4UBWS3hSZ616u5OciwUF108=",
        "From": "Laurent Pinchart <laurent.pinchart@ideasonboard.com>",
        "To": "libcamera-devel@lists.libcamera.org",
        "Date": "Tue,  1 Jan 2019 23:23:25 +0200",
        "Message-Id": "<20190101212328.18361-1-laurent.pinchart@ideasonboard.com>",
        "X-Mailer": "git-send-email 2.19.2",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "Subject": "[libcamera-devel] [PATCH 1/4] libcamera: mediadevice: Fix graph\n\tparsing error handling",
        "X-BeenThere": "libcamera-devel@lists.libcamera.org",
        "X-Mailman-Version": "2.1.23",
        "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": "Tue, 01 Jan 2019 21:22:34 -0000"
    },
    "content": "Most errors recorded during graph parsing are logged but not propagated\nto the caller. Fix this and delete objects that are created but not\nsuccessfully added to the graph to avoid memory leaks. As the error code\nreturned from the addObject() and populate*() functions doesn't matter\nmuch, turn them into bool functions.\n\nAdditionally, add a way to query whether the media graph was valid, and\nclear objects before populating the graph to avoid leaking them.\n\nSigned-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n---\n src/libcamera/include/media_device.h | 10 ++--\n src/libcamera/media_device.cpp       | 75 +++++++++++++++++-----------\n 2 files changed, 53 insertions(+), 32 deletions(-)",
    "diff": "diff --git a/src/libcamera/include/media_device.h b/src/libcamera/include/media_device.h\nindex bca7c9a19471..74a67c81398a 100644\n--- a/src/libcamera/include/media_device.h\n+++ b/src/libcamera/include/media_device.h\n@@ -28,6 +28,7 @@ public:\n \tvoid close();\n \n \tint populate();\n+\tbool valid() const { return valid_; }\n \n \tconst std::string driver() const { return driver_; }\n \tconst std::string devnode() const { return devnode_; }\n@@ -37,18 +38,19 @@ private:\n \tstd::string driver_;\n \tstd::string devnode_;\n \tint fd_;\n+\tbool valid_;\n \n \tstd::map<unsigned int, MediaObject *> objects_;\n \tMediaObject *object(unsigned int id);\n-\tint addObject(MediaObject *obj);\n+\tbool addObject(MediaObject *obj);\n \tvoid clear();\n \n \tstd::vector<MediaEntity *> entities_;\n \tMediaEntity *getEntityByName(const std::string &name);\n \n-\tvoid populateEntities(const struct media_v2_topology &topology);\n-\tint populatePads(const struct media_v2_topology &topology);\n-\tint populateLinks(const struct media_v2_topology &topology);\n+\tbool populateEntities(const struct media_v2_topology &topology);\n+\tbool populatePads(const struct media_v2_topology &topology);\n+\tbool populateLinks(const struct media_v2_topology &topology);\n };\n \n } /* namespace libcamera */\ndiff --git a/src/libcamera/media_device.cpp b/src/libcamera/media_device.cpp\nindex d9a5196ac28c..fd5a31746075 100644\n--- a/src/libcamera/media_device.cpp\n+++ b/src/libcamera/media_device.cpp\n@@ -56,7 +56,7 @@ namespace libcamera {\n  * \\param devnode The media device node path\n  */\n MediaDevice::MediaDevice(const std::string &devnode)\n-\t: devnode_(devnode), fd_(-1)\n+\t: devnode_(devnode), fd_(-1), valid_(false)\n {\n }\n \n@@ -99,6 +99,7 @@ void MediaDevice::clear()\n \n \tobjects_.clear();\n \tentities_.clear();\n+\tvalid_ = false;\n }\n \n /**\n@@ -163,18 +164,18 @@ void MediaDevice::close()\n  * Add a new object to the global objects pool and fail if the object\n  * has already been registered.\n  */\n-int MediaDevice::addObject(MediaObject *obj)\n+bool MediaDevice::addObject(MediaObject *obj)\n {\n \n \tif (objects_.find(obj->id()) != objects_.end()) {\n \t\tLOG(Error) << \"Element with id \" << obj->id()\n \t\t\t   << \" already enumerated.\";\n-\t\treturn -EEXIST;\n+\t\treturn false;\n \t}\n \n \tobjects_[obj->id()] = obj;\n \n-\treturn 0;\n+\treturn true;\n }\n \n /*\n@@ -201,7 +202,7 @@ MediaEntity *MediaDevice::getEntityByName(const std::string &name)\n \treturn nullptr;\n }\n \n-int MediaDevice::populateLinks(const struct media_v2_topology &topology)\n+bool MediaDevice::populateLinks(const struct media_v2_topology &topology)\n {\n \tmedia_v2_link *mediaLinks = reinterpret_cast<media_v2_link *>\n \t\t\t\t    (topology.ptr_links);\n@@ -222,7 +223,7 @@ int MediaDevice::populateLinks(const struct media_v2_topology &topology)\n \t\tif (!source) {\n \t\t\tLOG(Error) << \"Failed to find pad with id: \"\n \t\t\t\t   << source_id;\n-\t\t\treturn -ENODEV;\n+\t\t\treturn false;\n \t\t}\n \n \t\tunsigned int sink_id = mediaLinks[i].sink_id;\n@@ -231,20 +232,23 @@ int MediaDevice::populateLinks(const struct media_v2_topology &topology)\n \t\tif (!sink) {\n \t\t\tLOG(Error) << \"Failed to find pad with id: \"\n \t\t\t\t   << sink_id;\n-\t\t\treturn -ENODEV;\n+\t\t\treturn false;\n \t\t}\n \n \t\tMediaLink *link = new MediaLink(&mediaLinks[i], source, sink);\n+\t\tif (!addObject(link)) {\n+\t\t\tdelete link;\n+\t\t\treturn false;\n+\t\t}\n+\n \t\tsource->addLink(link);\n \t\tsink->addLink(link);\n-\n-\t\taddObject(link);\n \t}\n \n-\treturn 0;\n+\treturn true;\n }\n \n-int MediaDevice::populatePads(const struct media_v2_topology &topology)\n+bool MediaDevice::populatePads(const struct media_v2_topology &topology)\n {\n \tmedia_v2_pad *mediaPads = reinterpret_cast<media_v2_pad *>\n \t\t\t\t  (topology.ptr_pads);\n@@ -258,16 +262,19 @@ int MediaDevice::populatePads(const struct media_v2_topology &topology)\n \t\tif (!mediaEntity) {\n \t\t\tLOG(Error) << \"Failed to find entity with id: \"\n \t\t\t\t   << entity_id;\n-\t\t\treturn -ENODEV;\n+\t\t\treturn false;\n \t\t}\n \n \t\tMediaPad *pad = new MediaPad(&mediaPads[i], mediaEntity);\n-\t\tmediaEntity->addPad(pad);\n+\t\tif (!addObject(pad)) {\n+\t\t\tdelete pad;\n+\t\t\treturn false;\n+\t\t}\n \n-\t\taddObject(pad);\n+\t\tmediaEntity->addPad(pad);\n \t}\n \n-\treturn 0;\n+\treturn true;\n }\n \n /*\n@@ -275,17 +282,22 @@ int MediaDevice::populatePads(const struct media_v2_topology &topology)\n  * reference in the MediaObject global pool and in the global vector of\n  * entities.\n  */\n-void MediaDevice::populateEntities(const struct media_v2_topology &topology)\n+bool MediaDevice::populateEntities(const struct media_v2_topology &topology)\n {\n \tmedia_v2_entity *mediaEntities = reinterpret_cast<media_v2_entity *>\n \t\t\t\t\t (topology.ptr_entities);\n \n \tfor (unsigned int i = 0; i < topology.num_entities; ++i) {\n \t\tMediaEntity *entity = new MediaEntity(&mediaEntities[i]);\n+\t\tif (!addObject(entity)) {\n+\t\t\tdelete entity;\n+\t\t\treturn false;\n+\t\t}\n \n-\t\taddObject(entity);\n \t\tentities_.push_back(entity);\n \t}\n+\n+\treturn true;\n }\n \n /**\n@@ -311,6 +323,8 @@ int MediaDevice::populate()\n \t__u64 version = -1;\n \tint ret;\n \n+\tclear();\n+\n \t/*\n \t * Keep calling G_TOPOLOGY until the version number stays stable.\n \t */\n@@ -343,24 +357,29 @@ int MediaDevice::populate()\n \t}\n \n \t/* Populate entities, pads and links. */\n-\tpopulateEntities(topology);\n-\n-\tret = populatePads(topology);\n-\tif (ret)\n-\t\tgoto error_free_objs;\n-\n-\tret = populateLinks(topology);\n-error_free_objs:\n-\tif (ret)\n-\t\tclear();\n+\tif (populateEntities(topology) &&\n+\t    populatePads(topology) &&\n+\t    populateLinks(topology))\n+\t\tvalid_ = true;\n \n \tdelete[] links;\n \tdelete[] ents;\n \tdelete[] pads;\n \n-\treturn ret;\n+\tif (!valid_) {\n+\t\tclear();\n+\t\treturn -EINVAL;\n+\t}\n+\n+\treturn 0;\n }\n \n+/**\n+ * \\fn MediaDevice::valid()\n+ * \\brief Query whether the media graph is valid\n+ * \\return true if the media graph is valid, false otherwise\n+ */\n+\n /**\n  * \\var MediaDevice::objects_\n  * \\brief Global map of media objects (entities, pads, links) keyed by their\n",
    "prefixes": [
        "libcamera-devel",
        "1/4"
    ]
}