in reply to Re^2: is there a way to ensure some code is the last thing that is run?
in thread is there a way to ensure some code is the last thing that is run?

> Would it be (as a hack of course) then possible to graft something on to ensure that the nasty thing is undone as the last thing that happens?

Maybe by monkey patching DESTROY?

use strict; use warnings; package Blubb; sub new { my $this = bless {a=>42}; $this->{circular} = $this; } sub DESTROY { warn "DESTROY"; } package MAIN; my $b = Blubb->new; { no warnings 'redefine'; my $orig= \&Blubb::DESTROY; *Blubb::DESTROY = sub { $orig->(@_); warn "END"; }; }

DESTROY at c:/tmp/pm/destruct_end.pl line 12 during global destruction +. END at c:/tmp/pm/destruct_end.pl line 27 during global destruction.

Cheers Rolf
(addicted to the Perl Programming Language and ☆☆☆☆ :)
Je suis Charlie!

  • Comment on Re^3: is there a way to ensure some code is the last thing that is run? (monkey patching)
  • Select or Download Code

Replies are listed 'Best First'.
Re^4: is there a way to ensure some code is the last thing that is run? (SUPEREND)
by LanX (Saint) on Feb 03, 2017 at 13:13 UTC

    The following will demonstrate an approach to define a &SUPEREND::DESTROY which is run after all other global DESTROY()s happend.

    use strict; use warnings; package Blubb; sub new { my $this = bless {a=>42}; $this->{circular} = $this; } sub DESTROY { warn "DESTROY ". __PACKAGE__; } package SUPEREND; no warnings 'redefine'; my $orig_destroy= \&Blubb::DESTROY; my $persist = bless { count=>0}; *Blubb::DESTROY= sub { $orig_destroy->(@_); warn "Mini END"; $persist->{count}++; }; sub DESTROY { warn "DESTROY after $_[0]->{count} destroys ". __PACKAGE__; } package MAIN; my $b = Blubb->new; my $c = Blubb->new; my $d = Blubb->new;

    DESTROY Blubb at c:/tmp/pm/destruct_end.pl line 12 during global destr +uction. Mini END at c:/tmp/pm/destruct_end.pl line 25 during global destructio +n. DESTROY Blubb at c:/tmp/pm/destruct_end.pl line 12 during global destr +uction. Mini END at c:/tmp/pm/destruct_end.pl line 25 during global destructio +n. DESTROY Blubb at c:/tmp/pm/destruct_end.pl line 12 during global destr +uction. Mini END at c:/tmp/pm/destruct_end.pl line 25 during global destructio +n. DESTROY after 3 destroys SUPEREND at c:/tmp/pm/destruct_end.pl line 33 + during global destruction.

    Please note, that this can be extended to be a generic solution, because SUPEREND could parse all packages available and monkeypatch all DESTROYs there (if existent)

    Since $persist is referenced it's DESTROY will be run last.

    For syntactic sugar one could also make SUPEREND export a function SUPEREND(&) accepting a codeblock which is run by the DESTROY of $persist.

    Cheers Rolf
    (addicted to the Perl Programming Language and ☆☆☆☆ :)
    Je suis Charlie!

      I think in the general case you cannot have a SUPEREND or something like that.

      The reason is that this SUPEREND could again create an object and the destructor of that would again run later.

        > The reason is that this SUPEREND could again create an object and the destructor of that would again run later.

        I'm still wondering what you mean.

        This package is guaranteed to run the last possible (Perl coded) DESTROY, because the ref counter of $persist will only turn 0 after all wrapper ran. (see proof of concept)

        And you can put your desired code in that DESTROY.

        Furthermore you have full control of "SUPEREND" and all "created objects" (which would be handled by the same DESTROY() anyway)

        Of course there is still destruction happening afterwards, namely subs and package variables, but these are hard coded.

        And I wonder how you possibly want to run any code after destruction of subs???

        You stated you need to run the code to fix issues with misbehaving foreign modules.

        If this doesn't help, then it's most probably an XY Problem on your side

        Cheers Rolf
        (addicted to the Perl Programming Language and ☆☆☆☆ :)
        Je suis Charlie!

        > and the destructor of that would again run later.

        ? That is how it works!

        Cheers Rolf
        (addicted to the Perl Programming Language and ☆☆☆☆ :)
        Je suis Charlie!

      Lastestdestructor not superend
        > Lastestdestructor

        Rather LastDestructor.

        Or END_OF_DESTRUCTION or even ARMAGEDD_OFF

        Cheers Rolf
        (addicted to the Perl Programming Language and ☆☆☆☆ :)
        Je suis Charlie!