Show a patch.

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

{
    "id": 1590,
    "url": "https://patchwork.libcamera.org/api/1.1/patches/1590/?format=api",
    "web_url": "https://patchwork.libcamera.org/patch/1590/",
    "project": {
        "id": 1,
        "url": "https://patchwork.libcamera.org/api/1.1/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": "<20190703080007.21376-3-paul.elder@ideasonboard.com>",
    "date": "2019-07-03T08:00:02",
    "name": "[libcamera-devel,RFC,v2,2/7] libcamera: process, process manager: create process and manager classes",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": false,
    "hash": "7c7eba07664c4e8221ba5f15a82d4e4f2328b4f6",
    "submitter": {
        "id": 17,
        "url": "https://patchwork.libcamera.org/api/1.1/people/17/?format=api",
        "name": "Paul Elder",
        "email": "paul.elder@ideasonboard.com"
    },
    "delegate": null,
    "mbox": "https://patchwork.libcamera.org/patch/1590/mbox/",
    "series": [
        {
            "id": 392,
            "url": "https://patchwork.libcamera.org/api/1.1/series/392/?format=api",
            "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=392",
            "date": "2019-07-03T08:00:00",
            "name": "Add IPA process isolation",
            "version": 2,
            "mbox": "https://patchwork.libcamera.org/series/392/mbox/"
        }
    ],
    "comments": "https://patchwork.libcamera.org/api/patches/1590/comments/",
    "check": "pending",
    "checks": "https://patchwork.libcamera.org/api/patches/1590/checks/",
    "tags": {},
    "headers": {
        "Return-Path": "<paul.elder@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 A317061571\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed,  3 Jul 2019 10:00:27 +0200 (CEST)",
            "from neptunite.flets-east.jp\n\t(p1871204-ipngn14001hodogaya.kanagawa.ocn.ne.jp [153.220.127.204])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id E92C32F0;\n\tWed,  3 Jul 2019 10:00:25 +0200 (CEST)"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1562140827;\n\tbh=XM6yziVBkZ7Pax3Ys1Ef0sjD9obSjnwdVsQ3d7DkznU=;\n\th=From:To:Cc:Subject:Date:In-Reply-To:References:From;\n\tb=RohyaIp1jWZCHniU6MKgjVi9mtOYilE4vZ22sOh98OLucDIOSBfcxEqemrvOR0CEj\n\tU+dQHsAoRm16TixSzeU1TjFfxBHF6LBkOX6IeP1rTBkO+XJMISkbSJUwYdyupygrGB\n\tusS3CLki3DbdMUVxW5pWb5VcnnwdPJFry2vLx7as=",
        "From": "Paul Elder <paul.elder@ideasonboard.com>",
        "To": "libcamera-devel@lists.libcamera.org",
        "Date": "Wed,  3 Jul 2019 17:00:02 +0900",
        "Message-Id": "<20190703080007.21376-3-paul.elder@ideasonboard.com>",
        "X-Mailer": "git-send-email 2.20.1",
        "In-Reply-To": "<20190703080007.21376-1-paul.elder@ideasonboard.com>",
        "References": "<20190703080007.21376-1-paul.elder@ideasonboard.com>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "Subject": "[libcamera-devel] [RFC PATCH v2 2/7] libcamera: process,\n\tprocess manager: create process and manager classes",
        "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": "Wed, 03 Jul 2019 08:00:27 -0000"
    },
    "content": "Add a Process class to abstract a process, and a ProcessManager singleton\nto monitor and manage the processes.\n\nSigned-off-by: Paul Elder <paul.elder@ideasonboard.com>\n---\nNew in v2\n\n src/libcamera/include/process.h         |  35 ++++++\n src/libcamera/include/process_manager.h |  40 +++++++\n src/libcamera/meson.build               |   4 +\n src/libcamera/process.cpp               | 140 ++++++++++++++++++++++++\n src/libcamera/process_manager.cpp       | 104 ++++++++++++++++++\n 5 files changed, 323 insertions(+)\n create mode 100644 src/libcamera/include/process.h\n create mode 100644 src/libcamera/include/process_manager.h\n create mode 100644 src/libcamera/process.cpp\n create mode 100644 src/libcamera/process_manager.cpp",
    "diff": "diff --git a/src/libcamera/include/process.h b/src/libcamera/include/process.h\nnew file mode 100644\nindex 0000000..85c0163\n--- /dev/null\n+++ b/src/libcamera/include/process.h\n@@ -0,0 +1,35 @@\n+/* SPDX-License-Identifier: LGPL-2.1-or-later */\n+/*\n+ * Copyright (C) 2019, Google Inc.\n+ *\n+ * process.h - Process object\n+ */\n+#ifndef __LIBCAMERA_PROCESS_H__\n+#define __LIBCAMERA_PROCESS_H__\n+\n+#include <string>\n+#include <vector>\n+\n+namespace libcamera {\n+\n+class Process\n+{\n+public:\n+\tProcess();\n+\tvirtual ~Process();\n+\n+\tint exec(const std::string &path, const std::vector<std::string> &args, const std::vector<int> &fds);\n+\n+private:\n+\tpid_t pid_;\n+\tbool execed_;\n+\n+\t/* TODO better prototype, and implementation; emit finished signal */\n+\tvirtual void sigchldHandler() { };\n+\n+\tfriend class ProcessManager;\n+};\n+\n+} /* namespace libcamera */\n+\n+#endif /* __LIBCAMERA_PROCESS_H__ */\ndiff --git a/src/libcamera/include/process_manager.h b/src/libcamera/include/process_manager.h\nnew file mode 100644\nindex 0000000..9b4bf25\n--- /dev/null\n+++ b/src/libcamera/include/process_manager.h\n@@ -0,0 +1,40 @@\n+/* SPDX-License-Identifier: LGPL-2.1-or-later */\n+/*\n+ * Copyright (C) 2019, Google Inc.\n+ *\n+ * process_manager.h - Process manager\n+ */\n+#ifndef __LIBCAMERA_PROCESS_MANAGER_H__\n+#define __LIBCAMERA_PROCESS_MANAGER_H__\n+\n+#include \"process.h\"\n+\n+#include <string>\n+#include <vector>\n+\n+namespace libcamera {\n+\n+class EventNotifier;\n+\n+class ProcessManager\n+{\n+public:\n+\tint registerProcess(Process *proc);\n+\n+\tstatic ProcessManager *instance();\n+\n+private:\n+\tstd::vector<Process *> processes_;\n+\n+\tProcessManager();\n+\t~ProcessManager();\n+\tvoid sigchldHandler(int sig);\n+\n+\tint signalfd_;\n+\n+\tEventNotifier *fdEvent_;\n+};\n+\n+} /* namespace libcamera */\n+\n+#endif /* __LIBCAMERA_PROCESS_MANAGER_H__ */\ndiff --git a/src/libcamera/meson.build b/src/libcamera/meson.build\nindex 8075b1f..087b578 100644\n--- a/src/libcamera/meson.build\n+++ b/src/libcamera/meson.build\n@@ -20,6 +20,8 @@ libcamera_sources = files([\n     'media_object.cpp',\n     'object.cpp',\n     'pipeline_handler.cpp',\n+    'process.cpp',\n+    'process_manager.cpp',\n     'request.cpp',\n     'signal.cpp',\n     'stream.cpp',\n@@ -45,6 +47,8 @@ libcamera_headers = files([\n     'include/media_device.h',\n     'include/media_object.h',\n     'include/pipeline_handler.h',\n+    'include/process.h',\n+    'include/process_manager.h',\n     'include/utils.h',\n     'include/v4l2_device.h',\n     'include/v4l2_subdevice.h',\ndiff --git a/src/libcamera/process.cpp b/src/libcamera/process.cpp\nnew file mode 100644\nindex 0000000..ea7b58d\n--- /dev/null\n+++ b/src/libcamera/process.cpp\n@@ -0,0 +1,140 @@\n+/* SPDX-License-Identifier: LGPL-2.1-or-later */\n+/*\n+ * Copyright (C) 2019, Google Inc.\n+ *\n+ * process.cpp - Process object\n+ */\n+\n+#include \"process.h\"\n+\n+#include <algorithm>\n+#include <iostream>\n+#include <vector>\n+\n+#include <dirent.h>\n+#include <string.h>\n+#include <sys/socket.h>\n+#include <sys/types.h>\n+#include <unistd.h>\n+\n+#include \"ipa_module.h\"\n+#include \"log.h\"\n+#include \"process_manager.h\"\n+#include \"utils.h\"\n+\n+/**\n+ * \\file process.h\n+ * \\brief Process object\n+ *\n+ * TODO add stuff here\n+ */\n+\n+namespace libcamera {\n+\n+LOG_DEFINE_CATEGORY(Process)\n+\n+namespace {\n+\n+void closefrom_except(int from, const std::vector<int> &fds)\n+{\n+\tstd::vector<int> v(fds);\n+\tsort(v.begin(), v.end());\n+\n+\tDIR *dir = opendir(\"/proc/self/fd\");\n+\tif (!dir)\n+\t\treturn;\n+\n+\tstruct dirent *ent;\n+\twhile ((ent = readdir(dir)) != nullptr) {\n+\t\tint fd;\n+\t\tif (sscanf(ent->d_name, \"%d\", &fd) == 1 && fd >= from &&\n+\t\t    fd != dirfd(dir) && !std::binary_search(v.begin(), v.end(), fd))\n+\t\t\tclose(fd);\n+\t}\n+\n+\tclosedir(dir);\n+\treturn;\n+}\n+\n+}\n+\n+/**\n+ * \\class Process\n+ * \\brief Manager for processes\n+ *\n+ * TODO write this\n+ */\n+\n+Process::Process()\n+\t: pid_(-1), execed_(false)\n+{\n+}\n+\n+Process::~Process()\n+{\n+}\n+\n+/**\n+ * \\brief Fork and exec a process, and close fds\n+ * \\param[in] path Path to executable\n+ * \\param[in] args Arguments to pass to executable\n+ * \\param[in] fds Vector of file descriptors to keep open\n+ *\n+ * Fork a process, and exec the executable specified by path. Prior to\n+ * exec'ing, but after forking, all file descriptors except for those\n+ * specified in fds will be closed.\n+ *\n+ * All indexes of args will be incremented by 1 before being fed to exec(),\n+ * so args[0] should not need to be equal to path.\n+ *\n+ * \\return a positive socket file descriptor on successful fork, exec, and\n+ * closing the file descriptors, or a negative error code otherwise\n+ */\n+int Process::exec(const std::string &path, const std::vector<std::string> &args, const std::vector<int> &fds)\n+{\n+\tint childPid;\n+\n+\tif (execed_)\n+\t\treturn 0;\n+\n+\tif ((childPid = fork()) == -1) {\n+\t\tint err = errno;\n+\t\tLOG(Process, Error) << \"Failed to fork: \" << strerror(err);\n+\t\treturn err;\n+\t} else if (childPid) {\n+\t\tstd::cout << \"parent uid = \" << getuid() << std::endl;\n+\t\tpid_ = childPid;\n+\t\tProcessManager::instance()->registerProcess(this);\n+\n+\t\texeced_ = true;\n+\n+\t\treturn 0;\n+\t} else {\n+\t\tint ret;\n+\t\tif (unshare(CLONE_NEWUSER|CLONE_NEWNET)) {\n+\t\t\tret = -errno;\n+\t\t\tLOG(Process, Error)\n+\t\t\t\t<< \"Failed to isolate IPA: \" << strerror(-ret);\n+\t\t\texit(ret);\n+\t\t}\n+\n+\t\tstd::cout << \"child uid = \" << getuid() << std::endl;\n+\n+\t\tclosefrom_except(3, fds);\n+\n+\t\tconst char **argv = new const char *[args.size() + 2];\n+\t\tint len = args.size();\n+\t\targv[0] = path.c_str();\n+\t\tfor (int i = 0; i < len; i++)\n+\t\t\targv[i+1] = args[i].c_str();\n+\t\targv[len+1] = NULL;\n+\n+\t\texecv(path.c_str(), (char **)argv);\n+\n+\t\tret = -errno;\n+\t\tLOG(Process, Error) << \"Failed to exec: \" << strerror(-ret);\n+\t\texit(ret);\n+\t}\n+}\n+\n+} /* namespace libcamera */\ndiff --git a/src/libcamera/process_manager.cpp b/src/libcamera/process_manager.cpp\nnew file mode 100644\nindex 0000000..1ba0cfb\n--- /dev/null\n+++ b/src/libcamera/process_manager.cpp\n@@ -0,0 +1,104 @@\n+/* SPDX-License-Identifier: LGPL-2.1-or-later */\n+/*\n+ * Copyright (C) 2019, Google Inc.\n+ *\n+ * process_manager.cpp - Process manager\n+ */\n+\n+#include \"process_manager.h\"\n+\n+#include <algorithm>\n+#include <iostream>\n+#include <vector>\n+\n+#include <dirent.h>\n+#include <signal.h>\n+#include <string.h>\n+#include <sys/signalfd.h>\n+#include <sys/socket.h>\n+#include <sys/types.h>\n+#include <sys/wait.h>\n+#include <unistd.h>\n+\n+#include <libcamera/event_notifier.h>\n+\n+#include \"ipa_module.h\"\n+#include \"log.h\"\n+#include \"utils.h\"\n+\n+/**\n+ * \\file process_manager.h\n+ * \\brief Process manager\n+ *\n+ * TODO add stuff here\n+ */\n+\n+namespace libcamera {\n+\n+LOG_DEFINE_CATEGORY(ProcessManager)\n+\n+/**\n+ * \\class ProcessManager\n+ * \\brief Manager for processes\n+ *\n+ * TODO make this nicer\n+ */\n+\n+void ProcessManager::sigchldHandler(int sig)\n+{\n+\t/* TODO give the process the status? */\n+\tfor (Process *p : processes_)\n+\t\tif ((p->pid_ = waitpid(p->pid_, NULL, WNOHANG)))\n+\t\t\tp->sigchldHandler();\n+}\n+\n+\n+/**\n+ * \\brief Register process with process manager\n+ * \\param[in] proc Process to register\n+ *\n+ * Add proc to the process manager to manage.\n+ *\n+ * \\todo add things to manage\n+ *\n+ * \\return zero on success, or negative error value\n+ */\n+int ProcessManager::registerProcess(Process *proc)\n+{\n+\tprocesses_.push_back(proc);\n+\n+\treturn 0;\n+}\n+\n+ProcessManager::ProcessManager()\n+{\n+\tsigset_t mask;\n+\tsigemptyset(&mask);\n+\tsigaddset(&mask, SIGCHLD);\n+\n+\tsignalfd_ = signalfd(-1, &mask, SFD_NONBLOCK);\n+\tfdEvent_ = new EventNotifier(signalfd_, EventNotifier::Read);\n+}\n+\n+ProcessManager::~ProcessManager()\n+{\n+\tdelete fdEvent_;\n+\tclose(signalfd_);\n+}\n+\n+/**\n+ * \\brief Retrieve the Process manager instance\n+ *\n+ * The ProcessManager is a singleton and can't be constructed manually. This\n+ * function shall instead be used to retrieve the single global instance of the\n+ * manager.\n+ *\n+ * \\return The Process manager instance\n+ */\n+ProcessManager *ProcessManager::instance()\n+{\n+\tstatic ProcessManager processManager;\n+\treturn &processManager;\n+}\n+\n+} /* namespace libcamera */\n",
    "prefixes": [
        "libcamera-devel",
        "RFC",
        "v2",
        "2/7"
    ]
}