Patch Detail
Show a patch.
GET /api/patches/1590/?format=api
{ "id": 1590, "url": "https://patchwork.libcamera.org/api/patches/1590/?format=api", "web_url": "https://patchwork.libcamera.org/patch/1590/", "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": "<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/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/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" ] }