houseabsolute / Devel-StackTrace

An object representing a stack trace
https://metacpan.org/release/Devel-StackTrace/
Other
7 stars 13 forks source link

undef frame during global destruction #13

Open autarch opened 7 years ago

autarch commented 7 years ago

Migrated from rt.cpan.org #99095 (status was 'open')

Requestors:

From ether@cpan.org (@karenetheridge) on 2014-09-23 23:20:27:

I'm afraid I don't have a reproduction case to give you, but I'm seeing this (reliably) on one of my test systems:

Can't call method "as_string" on an undefined value at /var/local/CE/extlib/lib/perl5/Devel/StackTrace.pm line 243 during global destruction.

line 243 is $st .= $f->as_string( $first, $p ) . "\n";

Is it possible that some of the frames are being destroyed prematurely? Or simply that an error condition during global destruction should be treated differently?

autarch commented 7 years ago

From drolsky@cpan.org (@autarch) on 2014-10-05 16:20:11:

On Tue Sep 23 19:20:27 2014, ETHER wrote:

Is it possible that some of the frames are being destroyed prematurely? Or simply that an error condition during global destruction should be treated differently?

To answer your questions ... Yes, AFAIK objects can be destroyed in any old order during global destruction. And yes, I suspect that errors during global destruction should be treated differently, but I'm not sure whether this is up to D::ST or something higher up the stack.

jjatria commented 6 years ago

I'm looking at this ticket as part of this month's PRC.

One easy solution would be to skip over any frames that are undefined.

diff --git a/lib/Devel/StackTrace.pm b/lib/Devel/StackTrace.pm
index 68674d4..2629957 100644
--- a/lib/Devel/StackTrace.pm
+++ b/lib/Devel/StackTrace.pm
@@ -257,6 +257,7 @@ sub as_string {
         my $st    = q{};
         my $first = 1;
         for my $f (@frames) {
+            next unless $f;
             $st .= $f->as_string( $first, $p ) . "\n";
             $first = 0;
         }

But I'm afraid that this might hide information that would otherwise be useful, by giving the impression that there was never a frame there, rather than indicating that the frame that should have been there is no longer. So maybe a different message could be printed in that case.

A different problem is why would there be frames missing, and from what I can tell, as long as we are keeping a reference to the frame in $trace->{frames}, that should prevent the object from being destroyed. So I don't know why that might happen. Or am I missing something?

It would help to have some indication of what raises this error.

autarch commented 6 years ago

The reason the frames are undef is that object destruction order during global destruction (when the interpret is shutting down) is random. That means that the frame objects contained by a trace object can be destroyed before the trace object.

I'm honestly not sure this should be fixed at all. The warning is arguably giving you useful information (notably that you're doing something that's not going to work reliably). Hiding the warning seems like a bad idea.

We could, however, emit a warning something like You are attempting to stringify a Devel::StackTrace object where same of the frames are undefined. Are you trying to stringify this object during the global interpreter destruction phase? That is not going to work reliably. You should capture the stringified output and save it for use during global destruction if you need this data.

That's a mouthful but it might be helpful.