Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer
 
PerlMonks  

Understanding compiletime vs. runtime

by punkish (Priest)
on Feb 04, 2005 at 03:56 UTC ( [id://427915]=perlquestion: print w/replies, xml ) Need Help??

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

I have the following in my script
#!/usr/bin/perl -w BEGIN { open(STDERR, ">>foo.err") or die "invisible error"; warn localtime() . ": $0 started " . $/; } use strict; use Foo; start(); # start the program while (1) { process(); # the main program logic goto_sleep(); # goto sleep } ### and then, in Foo.pm ####### sub process { # create an IMAP connection eval { $imap = Mail::IMAPClient->new( Server => $IMAP, User => $UNAME, Password => $PWD, Uid => 0, Debug => $DEBUGGING, ) or carp "Cannot connect to $IMAP as $UNAME: $@"; }; open LOG, ">>foo.log"; print LOG ($@) ? "failed with $@\n" : "connected successfully\n"; close LOG; }

My logic is thusly -- if something is wrong enough for the script to not compile, it will write the reason in foo.err and die rightaway. However, if compilation is successful, then it will try to connect to the IMAP host. If that fails, it will write to foo.log and go to sleep for a specified time, and then wake up and try again.

Except, my logic is wrong. If the connection to the IMAP host fails, the error gets written to foo.err and the script dies. This indicates that the script is checking for the IMAP host connection right at compile time.

What am I doing wrong, and how can I achieve what I want?

What I want is -- after the script starts up successfully, I want it to make the connection to the IMAP host. If successful, do the rest of its stuff, else write a note in the log and go to sleep only to try again later.

Update: Stranger still... if the connection fails, I get an error in foo.err, and yet, I also get "connected successfully" in foo.log. This is most bewildering.

Replies are listed 'Best First'.
Re: Understanding compiletime vs. runtime
by tilly (Archbishop) on Feb 04, 2005 at 06:53 UTC
    Your expectation is that Mail::IMAPClient is using die or equivalent when it runs into errors, creating a trappable error.

    Your description of what is happening leads me to suspect that Mail::IMAPClient is just warning, which writes to STDERR (and therefore goes to foo.err) and leaves no trapped error (hence the "connected successfully" message).

    If my suspicion is correct, then you can get what you want with the line:

    $SIG{__WARN__} = sub {die @_};
    so that warnings become dies and get caught like you expect.

    But note that if STDERR is being written to directly (eg with "print STDERR") then you'll have to put in a lot more effort.

      full disclosure: The stuff in the BEGIN block is something I copied from another code (someone else's suggestion). It seemed to do what I wanted, so I haven't spent a lot of effort really understanding it.

      Now, putting some effort to understand it, I believe what I am ending up doing is redirecting all the errors to foo.err, and all non-errors to foo.log. Which is ok. As quite a pleasant sideeffect of my ignorance, that _is_ what I want.

      However -- I don't want to program to die as it seems to be doing. And, from your suggestion, it seems I will further insure that all warnings become dies. If, from what you say above, Mail::IMAPClient is just warning, why is the program die-ing?

      Btw, per thor's suggestion, perl -c script.pl sends script.pl syntax OK to foo.err.

      In the end -- I want there to be no die-ing at all, absolutely, unless a SIGINT is sent. In all cases other than a SIGINT, I want the error message written to foo.err and for the script to recover and merrily continue its way.

      Since the above is a fair bit beyond my current understanding, I need some guidance on how to implement it.

      Many thanks for your advice.

        Let me explain my suggestion in more detail.

        You're having errors in the eval, and you want to trap them. The eval will trap any die and store it in $@, which you're then processing. The problem is that a warn does not get trapped by eval, it just goes to STDERR. So the error is printed to that file, and then when you test $@ you have no sign that there was a problem.

        My suggestion turns warns into dies so that eval can trap them so that the code that you presented does something closer to what you say that you want. You're right that I've left warns as dies afterwards. That's fixable. In fact try the following variation of the eval and tell me whether it works better:

        # create an IMAP connection eval { # This is the inserted line. local $SIG{__WARN__} = sub {die @_}; $imap = Mail::IMAPClient->new( Server => $IMAP, User => $UNAME, Password => $PWD, Uid => 0, Debug => $DEBUGGING, ) or carp "Cannot connect to $IMAP as $UNAME: $@"; };
        I give you good odds that this will cause your eval to do what you want it to do, and it won't make warns into dies later in your program.
Re: Understanding compiletime vs. runtime
by thor (Priest) on Feb 04, 2005 at 04:57 UTC
    Why do you need to log things at compile time? If your script can't compile, it'll do nothing, so why worry about it? And, if you're worried about non-attended execution of a script that may or may not compile, you've got larger issues. It's really easy to run 'perl -c script.pl' before deployment...even though you should probably do more testing than that. Also, I don't think you can just open STDERR like that...you have to close it first and re-open it to a file of your choosing.

    thor

    Feel the white light, the light within
    Be your own disciple, fan the sparks of will
    For all of us waiting, your kingdom will come

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://427915]
Approved by Tanktalus
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others meditating upon the Monastery: (5)
As of 2024-04-23 16:18 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found