[{"id":20130,"web_url":"https://patchwork.libcamera.org/comment/20130/","msgid":"<163403487549.2837254.6838483552670347139@Monstersaurus>","date":"2021-10-12T10:34:35","subject":"Re: [libcamera-devel] [PATCH v2 1/4] libcamera: base: Add Backtrace\n\tclass","submitter":{"id":4,"url":"https://patchwork.libcamera.org/api/people/4/","name":"Kieran Bingham","email":"kieran.bingham@ideasonboard.com"},"content":"Quoting Laurent Pinchart (2021-10-03 23:36:03)\n> Create a new class to abstract generation and access to call stack\n> backtraces. The current implementation depends on the glibc backtrace()\n> implementation and is copied from the logger. Future development will\n> bring support for libunwind, transparently for the users of the class.\n> \n> The logger backtrace implementation is dropped, replaced by usage of the\n> new Backtrace class.\n> \n\nI like the abstraction here to support multiple backtracers, and of\ncourse like that we're going to get demangling from this series.\n\nReviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n\n> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> ---\n> Changes since v1:\n> \n> - Print message when backtrace isn't available\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         |  27 +++-----\n>  src/libcamera/base/meson.build     |   5 ++\n>  6 files changed, 155 insertions(+), 23 deletions(-)\n>  create mode 100644 include/libcamera/base/backtrace.h\n>  create mode 100644 src/libcamera/base/backtrace.cpp\n> \n> diff --git a/include/libcamera/base/backtrace.h b/include/libcamera/base/backtrace.h\n> new file mode 100644\n> index 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> +       Backtrace();\n> +\n> +       std::string toString(unsigned int skipLevels = 0) const;\n> +\n> +private:\n> +       LIBCAMERA_DISABLE_COPY(Backtrace)\n> +\n> +       std::vector<void *> backtrace_;\n> +};\n> +\n> +} /* namespace libcamera */\n> +\n> +#endif /* __LIBCAMERA_BASE_BACKTRACE_H__ */\n> diff --git a/include/libcamera/base/meson.build b/include/libcamera/base/meson.build\n> index 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',\n> diff --git a/meson.build b/meson.build\n> index 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\n> diff --git a/src/libcamera/base/backtrace.cpp b/src/libcamera/base/backtrace.cpp\n> new file mode 100644\n> index 000000000000..c010a7e42e4d\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 to 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> +       backtrace_.resize(32);\n\nI guess we can't get the backtrace size in advance?\n\n> +\n> +       int num_entries = backtrace(backtrace_.data(), backtrace_.size());\n> +       if (num_entries < 0) {\n> +               backtrace_.clear();\n> +               return;\n> +       }\n\nDoes that failure mean it went beyond 32? or does it cap at 32?\n\n\n> +\n> +       backtrace_.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> +       /* Skip the first entry, corresponding to the Backtrace construction. */\n> +       skipLevels += 1;\n> +\n> +       if (backtrace_.size() <= skipLevels)\n> +               return std::string();\n> +\n> +#if HAVE_BACKTRACE\n> +       Span<void *const> trace{ backtrace_ };\n> +       trace = trace.subspan(skipLevels);\n> +\n> +       char **strings = backtrace_symbols(trace.data(), trace.size());\n> +       if (strings) {\n> +               std::ostringstream msg;\n> +\n> +               for (unsigned int i = 0; i < trace.size(); ++i)\n> +                       msg << strings[i] << std::endl;\n> +\n> +               free(strings);\n> +               return msg.str();\n> +       }\n> +#endif\n> +\n> +       return std::string();\n> +}\n> +\n> +} /* namespace libcamera */\n> diff --git a/src/libcamera/base/log.cpp b/src/libcamera/base/log.cpp\n> index a3e3f9ea2712..64813b6607c5 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,22 @@ void Logger::write(const LogMessage &msg)\n>   */\n>  void Logger::backtrace()\n>  {\n> -#if HAVE_BACKTRACE\n>         std::shared_ptr<LogOutput> output = std::atomic_load(&output_);\n>         if (!output)\n>                 return;\n>  \n> -       void *buffer[32];\n> -       int num_entries = ::backtrace(buffer, std::size(buffer));\n> -       char **strings = backtrace_symbols(buffer, num_entries);\n> -       if (!strings)\n> -               return;\n> -\n> -       std::ostringstream msg;\n> -       msg << \"Backtrace:\" << std::endl;\n> -\n>         /*\n>          * Skip the first two entries that correspond to this function and\n>          * ~LogMessage().\n>          */\n> -       for (int i = 2; i < num_entries; ++i)\n> -               msg << strings[i] << std::endl;\n> +       std::string backtrace = Backtrace().toString(2);\n> +       if (backtrace.empty()) {\n> +               output->write(\"Backtrace not available\\n\");\n> +               return;\n> +       }\n>  \n> -       output->write(msg.str());\n> -\n> -       free(strings);\n> -#endif\n> +       output->write(\"Backtrace:\\n\");\n> +       output->write(backtrace);\n>  }\n>  \n>  /**\n> diff --git a/src/libcamera/base/meson.build b/src/libcamera/base/meson.build\n> index d17249a023e1..fc00296dfa8a 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> -- \n> Regards,\n> \n> Laurent Pinchart\n>","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 0FC5BC323E\n\tfor <parsemail@patchwork.libcamera.org>;\n\tTue, 12 Oct 2021 10:34:41 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 883F068F4D;\n\tTue, 12 Oct 2021 12:34:40 +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 6186C68F4C\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue, 12 Oct 2021 12:34:38 +0200 (CEST)","from pendragon.ideasonboard.com\n\t(cpc89244-aztw30-2-0-cust3082.18-1.cable.virginm.net [86.31.172.11])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id DF6ADF1\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue, 12 Oct 2021 12:34:37 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"PciWYW1E\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1634034878;\n\tbh=mUKCo2CzjxIUTkeQtpvzlaC1Wm2PhkHnNfYyI9KsZa0=;\n\th=In-Reply-To:References:Subject:From:To:Date:From;\n\tb=PciWYW1Ei0xPW68W+0dkcV8afe70zt+bfwrtdIFQqrv18od75s4HkvzTFObjXl/kX\n\tA3QI6dm6jcLyRgPiDNqRwD5guoV42txTktfYeqYvvonFl1PYu8kRXpzwn6wKSmGGiI\n\tcbPg3h0CZhrv+jSV0UJy1R+WAw1ks6mZLMcpAdi8=","Content-Type":"text/plain; charset=\"utf-8\"","MIME-Version":"1.0","Content-Transfer-Encoding":"quoted-printable","In-Reply-To":"<20211003223606.20016-2-laurent.pinchart@ideasonboard.com>","References":"<20211003223606.20016-1-laurent.pinchart@ideasonboard.com>\n\t<20211003223606.20016-2-laurent.pinchart@ideasonboard.com>","From":"Kieran Bingham <kieran.bingham@ideasonboard.com>","To":"libcamera-devel@lists.libcamera.org","Date":"Tue, 12 Oct 2021 11:34:35 +0100","Message-ID":"<163403487549.2837254.6838483552670347139@Monstersaurus>","User-Agent":"alot/0.9.1","Subject":"Re: [libcamera-devel] [PATCH v2 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>"}},{"id":20255,"web_url":"https://patchwork.libcamera.org/comment/20255/","msgid":"<20211018034218.GA2066071@pyrite.rasen.tech>","date":"2021-10-18T03:42:18","subject":"Re: [libcamera-devel] [PATCH v2 1/4] libcamera: base: Add Backtrace\n\tclass","submitter":{"id":17,"url":"https://patchwork.libcamera.org/api/people/17/","name":"Paul Elder","email":"paul.elder@ideasonboard.com"},"content":"Hi Laurent,\n\nOn Mon, Oct 04, 2021 at 01:36:03AM +0300, Laurent Pinchart wrote:\n> Create a new class to abstract generation and access to call stack\n> backtraces. The current implementation depends on the glibc backtrace()\n> implementation and is copied from the logger. Future development will\n> bring support for libunwind, transparently for the users of the class.\n> \n> The logger backtrace implementation is dropped, replaced by usage of the\n> new Backtrace class.\n> \n> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n\nReviewed-by: Paul Elder <paul.elder@ideasonboard.com>\n\n> ---\n> Changes since v1:\n> \n> - Print message when backtrace isn't available\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         |  27 +++-----\n>  src/libcamera/base/meson.build     |   5 ++\n>  6 files changed, 155 insertions(+), 23 deletions(-)\n>  create mode 100644 include/libcamera/base/backtrace.h\n>  create mode 100644 src/libcamera/base/backtrace.cpp\n> \n> diff --git a/include/libcamera/base/backtrace.h b/include/libcamera/base/backtrace.h\n> new file mode 100644\n> index 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__ */\n> diff --git a/include/libcamera/base/meson.build b/include/libcamera/base/meson.build\n> index 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',\n> diff --git a/meson.build b/meson.build\n> index 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\n> diff --git a/src/libcamera/base/backtrace.cpp b/src/libcamera/base/backtrace.cpp\n> new file mode 100644\n> index 000000000000..c010a7e42e4d\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 to 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 */\n> diff --git a/src/libcamera/base/log.cpp b/src/libcamera/base/log.cpp\n> index a3e3f9ea2712..64813b6607c5 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,22 @@ 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\toutput->write(\"Backtrace not available\\n\");\n> +\t\treturn;\n> +\t}\n>  \n> -\toutput->write(msg.str());\n> -\n> -\tfree(strings);\n> -#endif\n> +\toutput->write(\"Backtrace:\\n\");\n> +\toutput->write(backtrace);\n>  }\n>  \n>  /**\n> diff --git a/src/libcamera/base/meson.build b/src/libcamera/base/meson.build\n> index d17249a023e1..fc00296dfa8a 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> -- \n> Regards,\n> \n> Laurent Pinchart\n>","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 ECA3BC324C\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon, 18 Oct 2021 03:42:35 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 60AF968F59;\n\tMon, 18 Oct 2021 05:42:35 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 4B1EF60128\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 18 Oct 2021 05:42:27 +0200 (CEST)","from pyrite.rasen.tech (unknown\n\t[IPv6:2400:4051:61:600:2c71:1b79:d06d:5032])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id A0C5612A;\n\tMon, 18 Oct 2021 05:42:25 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"e91Owf2u\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1634528546;\n\tbh=xgGa2OXYoDe1QkE4NEBDganM4/HNbOd9wuGIU1Zm6e8=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=e91Owf2uCvg953eTOgl6UqjOa0n5SDOivzxCO6uocGz7LruRBKVsXbcJw7hoC03OJ\n\tdo+k25DzKmdLDuf6M+4RgyPe6HT7aEVhbVcgl9r1utslBKX4MlIlqrfG5MdpQTufNw\n\tekuecJ1vmyaOGgWoUo2c5MQ5vhKwombYr1GQepVQ=","Date":"Mon, 18 Oct 2021 12:42:18 +0900","From":"paul.elder@ideasonboard.com","To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","Message-ID":"<20211018034218.GA2066071@pyrite.rasen.tech>","References":"<20211003223606.20016-1-laurent.pinchart@ideasonboard.com>\n\t<20211003223606.20016-2-laurent.pinchart@ideasonboard.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=us-ascii","Content-Disposition":"inline","In-Reply-To":"<20211003223606.20016-2-laurent.pinchart@ideasonboard.com>","Subject":"Re: [libcamera-devel] [PATCH v2 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>","Cc":"libcamera-devel@lists.libcamera.org","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]