fokat has asked for the wisdom of the Perl Monks concerning the following question:

Fellow monks:

I come before you to request the help of your collective wisdom for this problem...

For a module I am writing, I want to create a kind of filter that removes extraneous data from the calls to methods that are defined by third party modules. In this particular example, I am failing miserably to do so with warnings::warn

*clone_warn = *warnings::warn; *warnings::warn = sub { print "Look ma!\n"; clone_warn(some_filter_function_i_provide @_); };

The problem is that as soon as I change warnings::warn, the alias I keep in clone_warn also changes, as would be expected. I've also tried any number of combinations of code references, closures, GLOBs to no avail.

What I want to achieve is the redefinition of the original function (warnings::warn) while keeping a reference to the original implementation, so that I can call it from my version. This is similar in concept to a proxy method or a call to ->SUPER::foo() in OO terms.

How can I achieve this? There has to be a way to do it...

Best regards

-lem, but some call me fokat

Replies are listed 'Best First'.
Re: How to stack a call to a class method
by Aristotle (Chancellor) on Mar 03, 2003 at 04:57 UTC
    I assume that on your part this is one of those not seeing the forest for the trees case. :) I know those too well.
    my $clone_warn = \&warnings::warn; *warnings::warn = sub { print "Look ma!\n"; $clone_warn->(some_filter_function_i_provide @_); };

    Just take a reference to whatever it was you want to keep..

    Update: clone_warn(foo) was an overlooked copypaste remnant.. It is a scalar holding a coderef of course.

    Makeshifts last the longest.

Re: How to stack a call to a class method
by demerphq (Chancellor) on Mar 03, 2003 at 13:23 UTC

    Perhaps I'm a little off base here, but are you really sure you are doing what you want to do? I can't think of any code that actually uses warnings::warn() at all, so I don't see why redefining it would be particularly useful. Redefining it won't affect CORE::warn, which you can only override through an import, and even then only within the scope of the module that does the use. (Healthy amounts of iirc here :-)

    You can however intercept calls to warn via $SIG{__WARN__}, however this approach is a little strange and has potential problems playing well with other modules/code.

    If this isnt the issue at hand then my apologies and Aristotles approach should do just fine. :-) (But an explanation of your underlying intentions would be welcome :-)

    ---
    demerphq


      I can't think of any code that actually uses warnings::warn() at all...

      % cd /usr/local/lib/perl5 % find . -type f -exec grep -l 'warnings::warn' {} \; ./5.8.0/alpha-dec_osf/DB_File.pm ./5.8.0/alpha-dec_osf/Socket.pm ./5.8.0/alpha-dec_osf/IO/Select.pm ./5.8.0/charnames.pm ./5.8.0/constant.pm ./5.8.0/open.pm ./5.8.0/overload.pm ./5.8.0/syslog.pl ./5.8.0/vars.pm ./5.8.0/warnings.pm ./5.8.0/Tie/Handle.pm ./5.8.0/Tie/Hash.pm ./5.8.0/Tie/Scalar.pm ./5.8.0/I18N/Collate.pm ./5.8.0/File/Find.pm ./5.8.0/Class/Struct.pm ./5.8.0/pod/perllexwarn.pod ./5.8.0/pod/perltoc.pod
      Not an overwhelmingly large list, but there are a few modules.

      blyman
      setenv EXINIT 'set noai ts=2'

        Yes true. And in fact if you had done a search on warnings::warnif() you probably would have found many more hits. Thanks for the correction.

        Although I didnt articulate this, what I was thinking of was that all output from warnings.pm are reported through CORE::warn() and CORE::die() (via Carp.pm) so overriding them (globally) or setting $SIG{__WARN__} and $SIG{__DIE__} to preprocess their arguments should resolve all user generated messages. The latter actually allows you to intercept Perl generated exceptions. Although in the case of a die() that won't be useful for much beyond changing the error message.

        ---
        demerphq


      Well demerphq, let me try to explain my intentions a bit more, although you might find this node informational so as to my purpose.

      (...) are you really sure you are doing what you want to do?

      I am not totally sure, but I am looking for a module that can help busy monks place some sort of protection against the vulnerability explained in the document referenced on this whitepaper until better measures can be applied by the respective module authors.

      (...)I can't think of any code that actually uses warnings::warn() at all, so I don't see why redefining it would be particularly useful.

      Certainly, at my company none of the code I've seen lately uses warnings::warn(), but I wanted to include it anyway just for completeness.

      (...) this approach is a little strange and has potential problems playing well with other modules/code.

      This is exactly where I would like enlightenment from you as well as other nodes. Please let's discuss that in this meditation. And thanks a lot for your answer.

      Best regards

      -lem, but some call me fokat