develooper Front page | perl.perl5.porters | Postings from September 2023

Re: Native stack traces?

Thread Previous | Thread Next
From:
demerphq
Date:
September 8, 2023 17:30
Subject:
Re: Native stack traces?
Message ID:
CANgJU+Ws-Cn4EN11MZJq0bPKHhGmmnhXgh-bddU-WbJVGH0qfw@mail.gmail.com
On Fri, 8 Sept 2023 at 18:52, Dave Mitchell <davem@iabyn.com> wrote:

> On Fri, Sep 08, 2023 at 04:52:16PM +0100, Paul "LeoNerd" Evans wrote:
> > At least for me, stacktraces fall below the criteria to bother spending
> > a lot of time on just at the moment, when there's so many other things
> > to be done. But of course that's not to stop anyone else who wishes to
> > have a go.
>
> On the other hand, the current 'package DB; @args = @DB::args' is a
> horrible hack. Perhaps once signatures have been properly implemented
> (with the original args kept on the stack rather than quietly being copied
> into @_ and accessed from there) it might be time to revisit the official
> API that perl provides to access the stack args, and come up up with
> something better? For example something that can extract the names of
> named parameters.
>
> But I think creating exception objects which can have stack trace info
> attached to them or similar, is a tad ambitious.
>
> PS:
>
> This quick-n-dirty sample code creates a full stack trace about 75,000
> times per second on my laptop. It sanitises the output by just listing the
> class or type of the arg, such as,
>
>     ./p:5 Foo::f(Foo, ARRAY, SCALAR, SCALAR, SCALAR, SCALAR, SCALAR)
>
> It shows that such code can be small and fast.
>
> Here goes:
>
>     package Foo;
>
>     f(bless({}, 'Foo'), [], qw(here's some args for f));
>
>     sub f { my $self = shift; $self->g(qw(args for g)) }
>     sub g { my $self = shift; $self->h(qw(h's args))   }
>     sub h {
>         my $self = shift;
>         for my $i (1..100_000) {
>             dump_stack();
>         }
>     }
>
>     sub dump_stack {
>         my @c;
>         my $i = 0;
>         my @frames;
>         package DB;
>         while (@c = caller(++$i)) {
>             my @args = map ref ? ref : ref \$_, @DB::args;
>             push @frames, "$c[1]:$c[2] $c[3](" . join(', ', @args) .
> ")\n";
>         }
>     }
>

That stack isnt very deep and the args on the stack aren't complex, and as
you said what it does with those arguments isnt very fancy. Also there are
a lot of subtleties that code leaves out. A typical use case for a stack
trace dump is to be called from a $SIG{__DIE__} handler, and in that
context you probably want to be careful about dealing with eval frames.
Either because you specifically *don't* want to serialize the stack from a
specific eval frame, or because you *do* want to do so, or a mixture of
both, where you want to ignore some eval frames at the top of the stack but
not those at the bottom.  So $^S comes up as a factor, and within a
web-server there is a very good chance you actually want to let the
developer decide if a given eval should disable the stack-trace or not, so
you end up needing code that counts the number of eval frames in the stack,
and provide a way for users to control how many evals to ignore. So a
simple implementation probably acquires additional functionality over time.
Consider that a good stack trace dumper used in a corporate setting
probably shouldnt accidentally dump credit card numbers and other sensitive
data, and you end up needing a fair bit of logic.

cheers,
Yves



-- 
perl -Mre=debug -e "/just|another|perl|hacker/"

Thread Previous | Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About