in reply to Re^3: How to redefine a modules private function?
in thread How to redefine a modules private function?

To wrap things up: it works and it doesn't.

The following code runs without errors.

Problem is that the handler is actually called before the redefinition happens. Which means the successful change of the constant (from "Dummy" to 666) is reversed again to 53 ...

use strict; use warnings; use Data::Dump qw/pp dd/; $|=1; BEGIN { $\="\n"; my $old = $SIG{__WARN__}; my $new_constant = sub() { 666 }; *ALIEN::DOMAIN_PORT_NEW = sub() { 666 }; $SIG{__WARN__} = sub { my ( $msg ) = @_ ; if ($msg =~ /Constant subroutine DOMAIN_PORT redefined/ ) { $SIG{__WARN__} = $old; print "REDEFINED", pp caller; print ALIEN::DOMAIN_PORT(); no warnings "redefine"; *ALIEN::DOMAIN_PORT_OLD = *ALIEN::DOMAIN_PORT; *ALIEN::DOMAIN_PORT = *ALIEN::DOMAIN_PORT_NEW; print ALIEN::DOMAIN_PORT(); } }; *ALIEN::DOMAIN_PORT = sub () {"DUMMY"}; } package ALIEN; sub DOMAIN_PORT() { 53 } BEGIN { print "pre compile"; } sub test { print "Inside test: ", DOMAIN_PORT; } test();

REDEFINED("main", "d:/tmp/pm/patch_constant.pl", 39) DUMMY 666 pre compile Inside test: 53

Cheers Rolf
(addicted to the Perl Programming Language :)
Wikisyntax for the Monastery

Replies are listed 'Best First'.
Re^5: How to redefine a modules private function? (works)
by LanX (Saint) on Mar 09, 2022 at 13:46 UTC
    But hooking into a later sub like a() actually works.

    But this kind of patching requires that the code never changes, tho it's arguably safer than a source-filter in disguise.

    use strict; use warnings; use Data::Dump qw/pp dd/; $|=1; my $DBG; BEGIN { $DBG=0; $\="\n"; my $old = $SIG{__WARN__}; $SIG{__WARN__} = sub { my ( $msg ) = @_ ; if ($msg =~ /Constant subroutine a redefined/ ) { $SIG{__WARN__} = $old; print "REDEFINED", pp caller if $DBG; no warnings 'redefine'; *ALIEN::DOMAIN_PORT = sub() { 666 }; } }; *ALIEN::a = sub () {"DUMMY"}; # cause redefine warning } # used package package ALIEN; # ---8<---- snippet from AnyEvent::DNS sub DOMAIN_PORT() { 53 } sub resolver (); sub a($$) { my ($domain, $cb) = @_; resolver->resolve ($domain => "a", sub { $cb->(map $_->[4], @_); }); } # --->8---- snippet from AnyEvent::DNS BEGIN { print "pre compile" if $DBG; } sub test { print "Inside test: ", DOMAIN_PORT; } test();

    Inside test: 666

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    Wikisyntax for the Monastery