Jay Savage                                                    
             <[EMAIL PROTECTED]                                             
             l.com>                                                     To 
                                       beginners perl <beginners@perl.org> 
             01/27/2006 11:20                                           cc 
             AM                                                            
                                                                   Subject 
                                       Re: use of uninitialized value....  
                                                                           
                                                                           
                                                                           
                                                                           
                                                                           
                                                                           







On 1/26/06, JupiterHost.Net <[EMAIL PROTECTED]> wrote:
> > The problem with defining your own versions of die, warn, croak, and
> > carp is that only your code uses them.  If another module croaks or
>
> Thats why you put it in a module and use it in all your scripts and if
> it has not already been done and you can find a proper place for it to
> go, out it on CPAN so every can use it.
>
>
> > dies then your custom error handling is not used.  This is why we have
> > access to $SIG{__DIE__} and $SIG{__WARN__} (croak() and carp()
> > internally use die() and warn() respectivly if I remember correctly).
>
> You are still "defining your own versions of die, warn, croak, and carp"
> and "only your code uses" still. Just differently :) but when you look
> at it later is it die()ing lile normal or custom or ??? having a good
> name for it makes it instantly recognizable and infinatelly easier to
> maintain:
>

The issue isn't who is setting the trap, the issue is how it behaves.
Defining subs as you have done only catches the errors you expect to
catch. If Net::FTP has a connection problem, it returns and error and
then your script calls your custom routine wich logs, emails, and then
calls die. If Net::FTP runs into an internal problem within the module
itself, though, it calls the default die which complanis to STDOUT and
quits. No log report. No email. Just silence unless you happen to be
sitting in front of the console when it happens. If you take the time
to trap the signals, though, when Net::FTP calls die interanlly, it
will get your trapped $SIG{__DIE__}, the error will be logged, and
you'll get an email.

The only way to duplicate this with a plain old sub would be to wrap
everything in eval blocks which is a pain, to say the least.

> For example:
>
> Say you're sorting through a 1200 line script I wrote 9 months ago and
> find this:
>
> die "oops I did it again: $!";
>
>
> Now is it:
>   a) standard die
>   b) send the error to email
>   c) INSERT it into a database
>   d) write it to a file
>   e) format it for HTML
>   f) none of the above
>   g) ask me, the original author, and hope I remember what sort of crack
> I was on that day (IE not gonna happen ;p)
>

It's die. There's no mystery about it. Siganls can only have one trap
at a time. 'Ctrl-s $SIG{__DIE__} = ' (or appropriate search for your
text editor) will make it all clear. You have to find where the
subroutnie is defined either way--_my_email_error is nice, but it
still doesn't tell you who's being emailed--and it's no more difficult
to find the code where the signal is trapped than it is to find the
code where the subroutine is defined. Signal trapping is just defining
a subrouting with a particular name. Why is finding the line that
looks like "sub _my_weird_carp {" easier than finding the line that
looks like "$SIG{__DIE__} = sub{"? if anything, the caps stick out in
the code and make handler defs easier to spot.

> However if it had been
>
> _die_to_email("oops I did it again: $!");
>
> _die_to_sql("oops I did it again: $!");
>
> _die_to_file("oops I did it again: $!");
>
> _die_to_html("oops I did it again: $!");
>
> Now I know *exactly* whats going on and pretty much where to look to see
> what its doing.
>
> Or at least, even _die("oops I did it again: $!"); (or in my initial
> example _my_die()) tells me its no normal die()
>
> You're right that %SIG is there so we can have our way with it (and is
> really handy when dealing with forks and children etc) but it doesn't
> mean we should (more ambiguous, more error prone, harder to maintain,
> etc etc)
>

No, %SIG is there because it's a standard best practice to use signals
to do the jobs they're designed for, and because reinventing the wheel
is pretty much universally frowned upon. Using standard features and
standard nomenclature facilitates maintenace, because not everyone
knows what the intention of _die_to_email() may be. Worse you may be
having an off day, or you may recommend this to a person who's not
quite as thorough. What if, instead of "_die_to_email()," you
programmer gets a little lazy and just calls the routine
"_email_error"? Is that an error to be emailed, or an error with
email? It maybe clear to you, but that doesn't mean it's clear to
everyone else. Every programmer, though, understands signal handlers
and how to use them; it's a basic practice, and not just in Perl.

>
> The bottom line is:
>
>   - both ways are fine

Under certain circumstances.

>   - using a function name that says what its doing makes it clear and
> easy to maintain

Yes, naming functions well is important.

>   - redefining the signal handlers is more ambiguous and problematic but
> allows you to change the behavior of built in exception handlers. (maybe
> more useful to add to a large existing script so it all of a sudden
> handles it how you want with only one change but past that feels more
> like a hack to me)

No, trapping signals is the clear, accepted, portable way to create
maintainable programs. If you find yourself dealing with a maintenance
programmer who's confused by them, you hired the wrong guy. Send him
back to school or hire somebody else.

>   - both ways make the OP's code way easier to read (what was the point
> of this thread originally anyway)
>

>Proabably.

>-- jay
>--------------------------------------------------
>This email and attachment(s): [  ] blogable; [ x ] ask first; [  ]
>private and confidential

>daggerquill [at] gmail [dot] com
>http://www.tuaw.com  http://www.dpguru.com  http://www.engatiki.org
>values of β will give rise to dom!


BEGIN DEREKs RESPONSE since I am a Lotus user >_<

Thanks Jay for the hopefully final wrap up to the uninteded long email
thread.  This was a good thing however b/c
I learned something new in this wonderful thing called Perl.
I agree and it make sense to use   $SIG{__DIE__} for obvious reasons.
But in my test code I am getting "Useless use of hash element in void
context at line 30."
which is the line that has the   $overide->{$error}.  But when I comment
out the mailme call I do not get this warning.

#!/usr/bin/perl
use strict;
use warnings;


       sub mailme {

                my $sub     =  shift;
                my $msg     =  MIME::Lite->new(
                From        => 'pshrapprd <[EMAIL PROTECTED]>',
                To          => 'Derek Smith <[EMAIL PROTECTED]>',
                Subject     => 'HRIS FTP Inbound to monster.com had
problems and or failed!',
                Type        => 'multipart/related');

                #$msg->attach(
                #Type            => 'TEXT',
                #Disposition     => 'attachment',
                #Path            => "$ftplog",
                #Filename        => "$ftplog");
                $msg->send;
        }




my $overide   = $SIG{__DIE__}; ## get error handler currently assigned to
die()
$SIG{__DIE__} = sub {
    my $error = shift;
    $overide->{$error} if (ref $overide);
    mailme($error);
};

open (LOG, "+</var/log/derek") or die "Was unable to open file: $!";
close (LOG);

Reply via email to