Räuber Hotzenplotz has asked for the wisdom of the Perl Monks concerning the following question:

Esteemed monks, I'm wondering whether there's a slick way to intercept messages that are printed to STDERR by a module I have no control over. Say, module SomeModule contained code like
package SomeModule; sub do_something { # ... something's going on ... print STDERR "D'oh! Error!"; }
which I call from main like
# What can I do here to direct STDERR messages # to errhandler() ? sub errhandler { ... } SomeModule::do_something();
Is there anything I can do with Tie::Handle or a similar module to intercept messages written to STDERR and direct them to errhandler()?

Replies are listed 'Best First'.
Re: Catch messages to STDERR
by Zaxo (Archbishop) on May 05, 2004 at 05:37 UTC

    Easier than that, wherever you want to capture:

    { open local(*STDERR), '>>', $filespec or die $!; # go on and do things close STDERR or die $!; }
    You can change the open call to a piped process or, in 5.8, a reference to a variable.

    Update: ++Corion picked up a typo in the code, corrected.

    After Compline,
    Zaxo

Re: Catch messages to STDERR
by hv (Prior) on May 05, 2004 at 10:54 UTC

    See Catching fork() with tied STDERR for one possible approach to this, and some discussion of the problems you might face if you take this approach. For your example you'd need to change the PRINT function in my tie class to something like:

    sub PRINT { my $self = shift; # the tied STDERR object errhandler(@_); }

    You could then wrap the call to the external function something like:

    tie *STDERR, 'My::Tie::Class'; SomeModule::do_something(); untie *STDERR;

    Hugo

Re: Catch messages to STDERR
by mifflin (Curate) on May 05, 2004 at 06:17 UTC
    Maybe you could use the __WARN__ signal.
    Something like...
    $SIG{__WARN__} = sub { SomeModule::errhandler(@_); };
    Now all warn, carp and cluck commands should get routed through this code.
Re: Catch messages to STDERR
by raptnor2 (Beadle) on May 05, 2004 at 21:38 UTC
    If I understand what you're doing, this is a neat idea. You can trap errors your way even though the author of the original module trapped them thier way. Perl is just cool...

    The following code catches all print operations on the STDERR file handle.

    package ErrorTrapper;
    
    sub TIEHANDLE{
        my ($class, $file) = @_;
        bless [] , $class;
    }
    
    sub PRINT{
        my ($self, @msg) = @_;
        die "@msg\n";
    }
    
    package main;
    
    tie *STDERR, "ErrorTrapper";
    
    print "Testing...\n\n";
    print STDERR "Something went wrong!\n";
    print "Shouldn't see this";
    
    Cheers,

    John

Re: Catch messages to STDERR
by DrHyde (Prior) on May 06, 2004 at 08:48 UTC