Patch Detail
Show a patch.
GET /api/patches/13920/?format=api
{ "id": 13920, "url": "https://patchwork.libcamera.org/api/patches/13920/?format=api", "web_url": "https://patchwork.libcamera.org/patch/13920/", "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": "<20210924102323.26787-2-laurent.pinchart@ideasonboard.com>", "date": "2021-09-24T10:23:20", "name": "[libcamera-devel,v1,1/4] libcamera: base: Add Backtrace class", "commit_ref": null, "pull_url": null, "state": "accepted", "archived": false, "hash": "d7001bdff1cda63cf055bb54e7fceaada835dd02", "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/13920/mbox/", "series": [ { "id": 2562, "url": "https://patchwork.libcamera.org/api/series/2562/?format=api", "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=2562", "date": "2021-09-24T10:23:19", "name": "libcamera: Improve backtraces", "version": 1, "mbox": "https://patchwork.libcamera.org/series/2562/mbox/" } ], "comments": "https://patchwork.libcamera.org/api/patches/13920/comments/", "check": "pending", "checks": "https://patchwork.libcamera.org/api/patches/13920/checks/", "tags": {}, "headers": { "Return-Path": "<libcamera-devel-bounces@lists.libcamera.org>", "X-Original-To": "parsemail@patchwork.libcamera.org", "Delivered-To": "parsemail@patchwork.libcamera.org", "Received": [ "from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 3EF2EBDC71\n\tfor <parsemail@patchwork.libcamera.org>;\n\tFri, 24 Sep 2021 10:23:34 +0000 (UTC)", "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id C6AEB6918E;\n\tFri, 24 Sep 2021 12:23:32 +0200 (CEST)", "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 6678969188\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 24 Sep 2021 12:23:30 +0200 (CEST)", "from pendragon.lan (62-78-145-57.bb.dnainternet.fi [62.78.145.57])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id F38F058B\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 24 Sep 2021 12:23:29 +0200 (CEST)" ], "Authentication-Results": "lancelot.ideasonboard.com;\n\tdkim=fail reason=\"signature verification failed\" (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"D7vZAUYh\"; dkim-atps=neutral", "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1632479010;\n\tbh=F2IZoMWoF4+WtC28hewYrMWvgMxM14jREP/nnwd5h0E=;\n\th=From:To:Subject:Date:In-Reply-To:References:From;\n\tb=D7vZAUYhW2BxKfy1gzjel9XbIjs/QPYFPxkrSDeXMnBq/ekPSoPfk2dBgUI/uWYYw\n\tHP7GSrMhdOMHcH5J0E494RvElioOUl7P3kZ2XKy3m8Kh/OXOZMf1yVXd+Z28PR4EUM\n\t1dMgf4ByH5XBHiPzNSEeqM094cCicO3mmqTaqmxU=", "From": "Laurent Pinchart <laurent.pinchart@ideasonboard.com>", "To": "libcamera-devel@lists.libcamera.org", "Date": "Fri, 24 Sep 2021 13:23:20 +0300", "Message-Id": "<20210924102323.26787-2-laurent.pinchart@ideasonboard.com>", "X-Mailer": "git-send-email 2.32.0", "In-Reply-To": "<20210924102323.26787-1-laurent.pinchart@ideasonboard.com>", "References": "<20210924102323.26787-1-laurent.pinchart@ideasonboard.com>", "MIME-Version": "1.0", "Content-Transfer-Encoding": "8bit", "Subject": "[libcamera-devel] [PATCH v1 1/4] libcamera: base: Add Backtrace\n\tclass", "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>", "Errors-To": "libcamera-devel-bounces@lists.libcamera.org", "Sender": "\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>" }, "content": "Create a new class to abstract generation and access to call stack\nbacktraces. The current implementation depends on the glibc backtrace()\nimplementation and is copied from the logger. Future development will\nbring support for libunwind, transparently for the users of the class.\n\nThe logger backtrace implementation is dropped, replaced by usage of the\nnew Backtrace class.\n\nSigned-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n---\n include/libcamera/base/backtrace.h | 34 +++++++++\n include/libcamera/base/meson.build | 1 +\n meson.build | 4 --\n src/libcamera/base/backtrace.cpp | 107 +++++++++++++++++++++++++++++\n src/libcamera/base/log.cpp | 25 ++-----\n src/libcamera/base/meson.build | 5 ++\n 6 files changed, 153 insertions(+), 23 deletions(-)\n create mode 100644 include/libcamera/base/backtrace.h\n create mode 100644 src/libcamera/base/backtrace.cpp", "diff": "diff --git a/include/libcamera/base/backtrace.h b/include/libcamera/base/backtrace.h\nnew file mode 100644\nindex 000000000000..aefc76defa83\n--- /dev/null\n+++ b/include/libcamera/base/backtrace.h\n@@ -0,0 +1,34 @@\n+/* SPDX-License-Identifier: LGPL-2.1-or-later */\n+/*\n+ * Copyright (C) 2021, Ideas on Board Oy\n+ *\n+ * backtrace.h - Call stack backtraces\n+ */\n+#ifndef __LIBCAMERA_BASE_BACKTRACE_H__\n+#define __LIBCAMERA_BASE_BACKTRACE_H__\n+\n+#include <string>\n+#include <vector>\n+\n+#include <libcamera/base/private.h>\n+\n+#include <libcamera/base/class.h>\n+\n+namespace libcamera {\n+\n+class Backtrace\n+{\n+public:\n+\tBacktrace();\n+\n+\tstd::string toString(unsigned int skipLevels = 0) const;\n+\n+private:\n+\tLIBCAMERA_DISABLE_COPY(Backtrace)\n+\n+\tstd::vector<void *> backtrace_;\n+};\n+\n+} /* namespace libcamera */\n+\n+#endif /* __LIBCAMERA_BASE_BACKTRACE_H__ */\ndiff --git a/include/libcamera/base/meson.build b/include/libcamera/base/meson.build\nindex 9feb4b9346d5..525aba9d2919 100644\n--- a/include/libcamera/base/meson.build\n+++ b/include/libcamera/base/meson.build\n@@ -3,6 +3,7 @@\n libcamera_base_include_dir = libcamera_include_dir / 'base'\n \n libcamera_base_headers = files([\n+ 'backtrace.h',\n 'bound_method.h',\n 'class.h',\n 'event_dispatcher.h',\ndiff --git a/meson.build b/meson.build\nindex a49c484fe64e..dfed01ba26bc 100644\n--- a/meson.build\n+++ b/meson.build\n@@ -29,10 +29,6 @@ cc = meson.get_compiler('c')\n cxx = meson.get_compiler('cpp')\n config_h = configuration_data()\n \n-if cc.has_header_symbol('execinfo.h', 'backtrace')\n- config_h.set('HAVE_BACKTRACE', 1)\n-endif\n-\n if cc.has_header_symbol('unistd.h', 'issetugid')\n config_h.set('HAVE_ISSETUGID', 1)\n endif\ndiff --git a/src/libcamera/base/backtrace.cpp b/src/libcamera/base/backtrace.cpp\nnew file mode 100644\nindex 000000000000..913f7ba71b03\n--- /dev/null\n+++ b/src/libcamera/base/backtrace.cpp\n@@ -0,0 +1,107 @@\n+/* SPDX-License-Identifier: LGPL-2.1-or-later */\n+/*\n+ * Copyright (C) 2021, Ideas on Board Oy\n+ *\n+ * backtrace.h - Call stack backtraces\n+ */\n+\n+#include <libcamera/base/backtrace.h>\n+\n+#if HAVE_BACKTRACE\n+#include <execinfo.h>\n+#include <stdlib.h>\n+#endif\n+\n+#include <sstream>\n+\n+#include <libcamera/base/span.h>\n+\n+/**\n+ * \\file backtrace.h\n+ * \\brief Generate call stack backtraces\n+ */\n+\n+namespace libcamera {\n+\n+/**\n+ * \\class Backtrace\n+ * \\brief Representation of a call stack backtrace\n+ *\n+ * The Backtrace class represents a function call stack. Constructing an\n+ * instance captures the call stack at the point the instance is constructed.\n+ * The instance can later be used to access the call stack and generate a\n+ * human-readable representation with the toString() function.\n+ *\n+ * Depending on the platform, different backends can be used to generate the\n+ * backtrace. The Backtrace class provides a best effort to capture accurate\n+ * backtraces, but doesn't offer any guarantee of a particular backtrace format.\n+ */\n+\n+/**\n+ * \\brief Construct a backtrace\n+ *\n+ * The backtrace captures the call stack at the point where it is constructed.\n+ * It can later be converted to a string with toString().\n+ */\n+Backtrace::Backtrace()\n+{\n+#if HAVE_BACKTRACE\n+\tbacktrace_.resize(32);\n+\n+\tint num_entries = backtrace(backtrace_.data(), backtrace_.size());\n+\tif (num_entries < 0) {\n+\t\tbacktrace_.clear();\n+\t\treturn;\n+\t}\n+\n+\tbacktrace_.resize(num_entries);\n+#endif\n+}\n+\n+/**\n+ * \\brief Convert a backtrace to a string representation\n+ * \\param[in] skipLevels Number of initial levels to skip in the backtrace\n+ *\n+ * The string representation of the backtrace is a multi-line string, with one\n+ * line per call stack entry. The format of the entries isn't specified and is\n+ * platform-dependent.\n+ *\n+ * The \\a skipLevels parameter indicates how many initial entries to skip from\n+ * the backtrace. This can be used to hide functions that wrap the construction\n+ * of the Backtrace instance from the call stack. The Backtrace constructor\n+ * itself is automatically skipped and never shown in the backtrace.\n+ *\n+ * If backtrace generation fails for any reason (usually because the platform\n+ * doesn't support this feature), an empty string is returned.\n+ *\n+ * \\return A string representation of the backtrace, or an empty string if\n+ * backtrace generation isn't possible\n+ */\n+std::string Backtrace::toString(unsigned int skipLevels) const\n+{\n+\t/* Skip the first entry, corresponding to the Backtrace construction. */\n+\tskipLevels += 1;\n+\n+\tif (backtrace_.size() <= skipLevels)\n+\t\treturn std::string();\n+\n+#if HAVE_BACKTRACE\n+\tSpan<void *const> trace{ backtrace_ };\n+\ttrace = trace.subspan(skipLevels);\n+\n+\tchar **strings = backtrace_symbols(trace.data(), trace.size());\n+\tif (strings) {\n+\t\tstd::ostringstream msg;\n+\n+\t\tfor (unsigned int i = 0; i < trace.size(); ++i)\n+\t\t\tmsg << strings[i] << std::endl;\n+\n+\t\tfree(strings);\n+\t\treturn msg.str();\n+\t}\n+#endif\n+\n+\treturn std::string();\n+}\n+\n+} /* namespace libcamera */\ndiff --git a/src/libcamera/base/log.cpp b/src/libcamera/base/log.cpp\nindex a3e3f9ea2712..272c440589d4 100644\n--- a/src/libcamera/base/log.cpp\n+++ b/src/libcamera/base/log.cpp\n@@ -8,9 +8,6 @@\n #include <libcamera/base/log.h>\n \n #include <array>\n-#if HAVE_BACKTRACE\n-#include <execinfo.h>\n-#endif\n #include <fstream>\n #include <iostream>\n #include <list>\n@@ -23,6 +20,7 @@\n \n #include <libcamera/logging.h>\n \n+#include <libcamera/base/backtrace.h>\n #include <libcamera/base/thread.h>\n #include <libcamera/base/utils.h>\n \n@@ -418,31 +416,20 @@ void Logger::write(const LogMessage &msg)\n */\n void Logger::backtrace()\n {\n-#if HAVE_BACKTRACE\n \tstd::shared_ptr<LogOutput> output = std::atomic_load(&output_);\n \tif (!output)\n \t\treturn;\n \n-\tvoid *buffer[32];\n-\tint num_entries = ::backtrace(buffer, std::size(buffer));\n-\tchar **strings = backtrace_symbols(buffer, num_entries);\n-\tif (!strings)\n-\t\treturn;\n-\n-\tstd::ostringstream msg;\n-\tmsg << \"Backtrace:\" << std::endl;\n-\n \t/*\n \t * Skip the first two entries that correspond to this function and\n \t * ~LogMessage().\n \t */\n-\tfor (int i = 2; i < num_entries; ++i)\n-\t\tmsg << strings[i] << std::endl;\n+\tstd::string backtrace = Backtrace().toString(2);\n+\tif (backtrace.empty())\n+\t\treturn;\n \n-\toutput->write(msg.str());\n-\n-\tfree(strings);\n-#endif\n+\toutput->write(\"Backtrace:\\n\");\n+\toutput->write(backtrace);\n }\n \n /**\ndiff --git a/src/libcamera/base/meson.build b/src/libcamera/base/meson.build\nindex 8e125744d823..85af01a19365 100644\n--- a/src/libcamera/base/meson.build\n+++ b/src/libcamera/base/meson.build\n@@ -1,6 +1,7 @@\n # SPDX-License-Identifier: CC0-1.0\n \n libcamera_base_sources = files([\n+ 'backtrace.cpp',\n 'class.cpp',\n 'bound_method.cpp',\n 'event_dispatcher.cpp',\n@@ -18,6 +19,10 @@ libcamera_base_sources = files([\n 'utils.cpp',\n ])\n \n+if cc.has_header_symbol('execinfo.h', 'backtrace')\n+ config_h.set('HAVE_BACKTRACE', 1)\n+endif\n+\n libcamera_base_deps = [\n dependency('threads'),\n libatomic,\n", "prefixes": [ "libcamera-devel", "v1", "1/4" ] }