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);