public inbox for isar-users@googlegroups.com
 help / color / mirror / Atom feed
From: "'Jan Kiszka' via isar-users" <isar-users@googlegroups.com>
To: Felix Moessbauer <felix.moessbauer@siemens.com>,
	isar-users@googlegroups.com
Cc: wzh@ilbers.de
Subject: Re: [PATCH v2 2/2] bitbake: Remove custom exception backtrace formatting
Date: Fri, 6 Mar 2026 17:40:02 +0100	[thread overview]
Message-ID: <c22c8903-caf2-415f-8d61-e5f2003290ec@siemens.com> (raw)
In-Reply-To: <20260306161548.1102004-3-felix.moessbauer@siemens.com>

Missing original author and signed-off.

Jan

On 06.03.26 17:15, Felix Moessbauer wrote:
> Backport of upstream bitbake patch c25e7ed128b9fd5b53d28d678238e2f3af52ef8b.
> 
> Removes the code in bitbake to show custom backtrace formatting for
> exceptions. In particular, the bitbake exception code prints function
> arguments, which while helpful is a security problem when passwords and
> other secrets can be passed as function arguments.
> 
> As it turns out, the handling of the custom serialized exception stack
> frames was pretty much made obsolete by d7db75020ed ("event/msg: Pass
> formatted exceptions"), which changed the events to pass a preformatted
> stacktrack list of strings, but the passing of the serialized data was
> never removed.
> 
> Change all the code to use the python traceback API to format exceptions
> instead of the custom code; conveniently traceback.format_exception()
> also returns a list of stack trace strings, so it can be used as a drop
> in replacement for bb.exception.format_exception()
> 
> [Felix: adjusted to bitbake path in isar repo]
> 
> Signed-off-by: Felix Moessbauer <felix.moessbauer@siemens.com>
> ---
>  bitbake/lib/bb/cooker.py      | 32 +++++++++---
>  bitbake/lib/bb/event.py       |  9 +---
>  bitbake/lib/bb/exceptions.py  | 96 -----------------------------------
>  bitbake/lib/bb/msg.py         |  4 --
>  bitbake/lib/bb/ui/teamcity.py |  5 --
>  5 files changed, 25 insertions(+), 121 deletions(-)
>  delete mode 100644 bitbake/lib/bb/exceptions.py
> 
> diff --git a/bitbake/lib/bb/cooker.py b/bitbake/lib/bb/cooker.py
> index c5bfef55..701cf51b 100644
> --- a/bitbake/lib/bb/cooker.py
> +++ b/bitbake/lib/bb/cooker.py
> @@ -17,7 +17,7 @@ import threading
>  from io import StringIO, UnsupportedOperation
>  from contextlib import closing
>  from collections import defaultdict, namedtuple
> -import bb, bb.exceptions, bb.command
> +import bb, bb.command
>  from bb import utils, data, parse, event, cache, providers, taskdata, runqueue, build
>  import queue
>  import signal
> @@ -2098,7 +2098,6 @@ class Parser(multiprocessing.Process):
>          except Exception as exc:
>              tb = sys.exc_info()[2]
>              exc.recipe = filename
> -            exc.traceback = list(bb.exceptions.extract_traceback(tb, context=3))
>              return True, None, exc
>          # Need to turn BaseExceptions into Exceptions here so we gracefully shutdown
>          # and for example a worker thread doesn't just exit on its own in response to
> @@ -2299,8 +2298,12 @@ class CookerParser(object):
>              return False
>          except ParsingFailure as exc:
>              self.error += 1
> -            logger.error('Unable to parse %s: %s' %
> -                     (exc.recipe, bb.exceptions.to_string(exc.realexception)))
> +
> +            exc_desc = str(exc)
> +            if isinstance(exc, SystemExit) and not isinstance(exc.code, str):
> +                exc_desc = 'Exited with "%d"' % exc.code
> +
> +            logger.error('Unable to parse %s: %s' % (exc.recipe, exc_desc))
>              self.shutdown(clean=False)
>              return False
>          except bb.parse.ParseError as exc:
> @@ -2309,20 +2312,33 @@ class CookerParser(object):
>              self.shutdown(clean=False, eventmsg=str(exc))
>              return False
>          except bb.data_smart.ExpansionError as exc:
> +            def skip_frames(f, fn_prefix):
> +                while f and f.tb_frame.f_code.co_filename.startswith(fn_prefix):
> +                    f = f.tb_next
> +                return f
> +
>              self.error += 1
>              bbdir = os.path.dirname(__file__) + os.sep
> -            etype, value, _ = sys.exc_info()
> -            tb = list(itertools.dropwhile(lambda e: e.filename.startswith(bbdir), exc.traceback))
> +            etype, value, tb = sys.exc_info()
> +
> +            # Remove any frames where the code comes from bitbake. This
> +            # prevents deep (and pretty useless) backtraces for expansion error
> +            tb = skip_frames(tb, bbdir)
> +            cur = tb
> +            while cur:
> +                cur.tb_next = skip_frames(cur.tb_next, bbdir)
> +                cur = cur.tb_next
> +
>              logger.error('ExpansionError during parsing %s', value.recipe,
>                           exc_info=(etype, value, tb))
>              self.shutdown(clean=False)
>              return False
>          except Exception as exc:
>              self.error += 1
> -            etype, value, tb = sys.exc_info()
> +            _, value, _ = sys.exc_info()
>              if hasattr(value, "recipe"):
>                  logger.error('Unable to parse %s' % value.recipe,
> -                            exc_info=(etype, value, exc.traceback))
> +                            exc_info=sys.exc_info())
>              else:
>                  # Most likely, an exception occurred during raising an exception
>                  import traceback
> diff --git a/bitbake/lib/bb/event.py b/bitbake/lib/bb/event.py
> index 4761c868..952c85c0 100644
> --- a/bitbake/lib/bb/event.py
> +++ b/bitbake/lib/bb/event.py
> @@ -19,7 +19,6 @@ import sys
>  import threading
>  import traceback
>  
> -import bb.exceptions
>  import bb.utils
>  
>  # This is the pid for which we should generate the event. This is set when
> @@ -759,13 +758,7 @@ class LogHandler(logging.Handler):
>  
>      def emit(self, record):
>          if record.exc_info:
> -            etype, value, tb = record.exc_info
> -            if hasattr(tb, 'tb_next'):
> -                tb = list(bb.exceptions.extract_traceback(tb, context=3))
> -            # Need to turn the value into something the logging system can pickle
> -            record.bb_exc_info = (etype, value, tb)
> -            record.bb_exc_formatted = bb.exceptions.format_exception(etype, value, tb, limit=5)
> -            value = str(value)
> +            record.bb_exc_formatted = traceback.format_exception(*record.exc_info)
>              record.exc_info = None
>          fire(record, None)
>  
> diff --git a/bitbake/lib/bb/exceptions.py b/bitbake/lib/bb/exceptions.py
> deleted file mode 100644
> index 801db9c8..00000000
> --- a/bitbake/lib/bb/exceptions.py
> +++ /dev/null
> @@ -1,96 +0,0 @@
> -#
> -# Copyright BitBake Contributors
> -#
> -# SPDX-License-Identifier: GPL-2.0-only
> -#
> -
> -import inspect
> -import traceback
> -import bb.namedtuple_with_abc
> -from collections import namedtuple
> -
> -
> -class TracebackEntry(namedtuple.abc):
> -    """Pickleable representation of a traceback entry"""
> -    _fields = 'filename lineno function args code_context index'
> -    _header = '  File "{0.filename}", line {0.lineno}, in {0.function}{0.args}'
> -
> -    def format(self, formatter=None):
> -        if not self.code_context:
> -            return self._header.format(self) + '\n'
> -
> -        formatted = [self._header.format(self) + ':\n']
> -
> -        for lineindex, line in enumerate(self.code_context):
> -            if formatter:
> -                line = formatter(line)
> -
> -            if lineindex == self.index:
> -                formatted.append('    >%s' % line)
> -            else:
> -                formatted.append('     %s' % line)
> -        return formatted
> -
> -    def __str__(self):
> -        return ''.join(self.format())
> -
> -def _get_frame_args(frame):
> -    """Get the formatted arguments and class (if available) for a frame"""
> -    arginfo = inspect.getargvalues(frame)
> -
> -    try:
> -        if not arginfo.args:
> -            return '', None
> -    # There have been reports from the field of python 2.6 which doesn't 
> -    # return a namedtuple here but simply a tuple so fallback gracefully if
> -    # args isn't present.
> -    except AttributeError:
> -        return '', None
> -
> -    firstarg = arginfo.args[0]
> -    if firstarg == 'self':
> -        self = arginfo.locals['self']
> -        cls = self.__class__.__name__
> -
> -        arginfo.args.pop(0)
> -        del arginfo.locals['self']
> -    else:
> -        cls = None
> -
> -    formatted = inspect.formatargvalues(*arginfo)
> -    return formatted, cls
> -
> -def extract_traceback(tb, context=1):
> -    frames = inspect.getinnerframes(tb, context)
> -    for frame, filename, lineno, function, code_context, index in frames:
> -        formatted_args, cls = _get_frame_args(frame)
> -        if cls:
> -            function = '%s.%s' % (cls, function)
> -        yield TracebackEntry(filename, lineno, function, formatted_args,
> -                             code_context, index)
> -
> -def format_extracted(extracted, formatter=None, limit=None):
> -    if limit:
> -        extracted = extracted[-limit:]
> -
> -    formatted = []
> -    for tracebackinfo in extracted:
> -        formatted.extend(tracebackinfo.format(formatter))
> -    return formatted
> -
> -
> -def format_exception(etype, value, tb, context=1, limit=None, formatter=None):
> -    formatted = ['Traceback (most recent call last):\n']
> -
> -    if hasattr(tb, 'tb_next'):
> -        tb = extract_traceback(tb, context)
> -
> -    formatted.extend(format_extracted(tb, formatter, limit))
> -    formatted.extend(traceback.format_exception_only(etype, value))
> -    return formatted
> -
> -def to_string(exc):
> -    if isinstance(exc, SystemExit):
> -        if not isinstance(exc.code, str):
> -            return 'Exited with "%d"' % exc.code
> -    return str(exc)
> diff --git a/bitbake/lib/bb/msg.py b/bitbake/lib/bb/msg.py
> index 3e18596f..4f616ff4 100644
> --- a/bitbake/lib/bb/msg.py
> +++ b/bitbake/lib/bb/msg.py
> @@ -89,10 +89,6 @@ class BBLogFormatter(logging.Formatter):
>              msg = logging.Formatter.format(self, record)
>          if hasattr(record, 'bb_exc_formatted'):
>              msg += '\n' + ''.join(record.bb_exc_formatted)
> -        elif hasattr(record, 'bb_exc_info'):
> -            etype, value, tb = record.bb_exc_info
> -            formatted = bb.exceptions.format_exception(etype, value, tb, limit=5)
> -            msg += '\n' + ''.join(formatted)
>          return msg
>  
>      def colorize(self, record):
> diff --git a/bitbake/lib/bb/ui/teamcity.py b/bitbake/lib/bb/ui/teamcity.py
> index fca46c28..7eeaab8d 100644
> --- a/bitbake/lib/bb/ui/teamcity.py
> +++ b/bitbake/lib/bb/ui/teamcity.py
> @@ -30,7 +30,6 @@ import bb.build
>  import bb.command
>  import bb.cooker
>  import bb.event
> -import bb.exceptions
>  import bb.runqueue
>  from bb.ui import uihelper
>  
> @@ -102,10 +101,6 @@ class TeamcityLogFormatter(logging.Formatter):
>          details = ""
>          if hasattr(record, 'bb_exc_formatted'):
>              details = ''.join(record.bb_exc_formatted)
> -        elif hasattr(record, 'bb_exc_info'):
> -            etype, value, tb = record.bb_exc_info
> -            formatted = bb.exceptions.format_exception(etype, value, tb, limit=5)
> -            details = ''.join(formatted)
>  
>          if record.levelno in [bb.msg.BBLogFormatter.ERROR, bb.msg.BBLogFormatter.CRITICAL]:
>              # ERROR gets a separate errorDetails field

-- 
Siemens AG, Foundational Technologies
Linux Expert Center

-- 
You received this message because you are subscribed to the Google Groups "isar-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to isar-users+unsubscribe@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/isar-users/c22c8903-caf2-415f-8d61-e5f2003290ec%40siemens.com.

  reply	other threads:[~2026-03-06 16:40 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-03-06 16:15 [PATCH v2 0/2] bitbake: Update to 2.8.1 release (no update!) 'Felix Moessbauer' via isar-users
2026-03-06 16:15 ` [PATCH v2 1/2] partial revert of "Bitbake: use LAYERDIR_RE when setting BBFILE_PATTERN_x" 'Felix Moessbauer' via isar-users
2026-03-06 16:15 ` [PATCH v2 2/2] bitbake: Remove custom exception backtrace formatting 'Felix Moessbauer' via isar-users
2026-03-06 16:40   ` 'Jan Kiszka' via isar-users [this message]
2026-03-10 11:21   ` Anton Mikanovich
2026-03-09  9:56 ` [PATCH v2 0/2] bitbake: Update to 2.8.1 release (no update!) Zhihang Wei
2026-03-09 11:07   ` 'MOESSBAUER, Felix' via isar-users
2026-03-09 12:37     ` 'Jan Kiszka' via isar-users

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=c22c8903-caf2-415f-8d61-e5f2003290ec@siemens.com \
    --to=isar-users@googlegroups.com \
    --cc=felix.moessbauer@siemens.com \
    --cc=jan.kiszka@siemens.com \
    --cc=wzh@ilbers.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox