http://qs321.pair.com?node_id=45547


in reply to Stupid question

Nearly every Perl script I write follows this format:

#!/usr/bin/perl -w use strict; use Other::Modules qw< ImportedFunction >; use vars qw< $Globals >; Main( @ARGV ); exit; sub Routine { ... } BEGIN { my $static= "Initial value"; sub usesStatic { ... } } sub Main { my $putMainVarsHere; ... } __END__
So you can prevent your subroutine from accessing your "main" variables by putting them where I wrote $putMainVarsHere.

This style has evolved for quite a while and there are specific reasons for almost every aspect of it. I find it catches quite a few errors for me.

I was going to explain my reasons for most aspects of this style, but I decided that that would be more appropriate elsewhere.

(updated twice)

Update: Here are some justifications for some of my decisions that I collected quite a while ago planning to write this up more formally. Instead I've just moved them from my scratchpad to here:

        - tye (but my friends call me "Tye")

Replies are listed 'Best First'.
Re^2: Stupid question
by runrig (Abbot) on May 19, 2011 at 16:29 UTC

    Posted only to maybe help someone else at some point in time...

    Update: It's all about this Carp bug (w/this solution) and modifying global variables ( @ARGV in this case - GetOptions modifies @ARGV ) after they get passed to functions.

    Although I agree with this format (but have mostly not gotten in the habit of using it myself), one of my co-workers was doing something similar, and got the following error during a Carp::confess from deep within the code (perl 5.8.8 - and we could not come up with a simple test case):

    Bizarre copy of HASH in sassign at ...../Carp/Heavy.pm line 45

    Although it seemed to be a completely unrelated part of the code, moving the Getopt::Long::GetOptions() call from inside to outside of Main() fixed the problem, and we got the proper confess with stack trace that we wanted to see. Though I'm sure when something with this much deep magic goes wrong, we've probably only fixed a symptom of the problem :-)

      Yes, those kind of errors are where any random change can prevent / postpone the error. For example, running under the Perl debugger is frequently one way to make the error go away. This can be a convenient way to get the stack trace and it can be very inconvenient in preventing you from being able to use the debugger to get more information. I've also often seen turning up trace or adding "debug prints" make such bugs no longer reproduce.

      But such voodoo changes usually just postpone the problem for a while.

      I'm glad you got the call stack and were able to use that to debug the problem that was causing Carp to be called. But if I were in your shoes, then I would be worried of other things eventually causing more "bizarre copy" panics.

      In such cases, I usually look for a minor Perl upgrade, upgrades for XS-using modules, or elimination of the use of some XS-using modules.

      Also, these bugs are much more likely in an environment like a Perl daemon or like mod_perl where you have an interpreter instance that runs for quite a long time doing tons of things. Re-spawning the daemon periodically or configuring mod_perl to restart children a bit more often can reduce the frequency of such bugs appearing.

      - tye        

        The "bizarre copy" errors from Carp so far seem to only happen when one particular module wants to throw an error (unless I do something like this on purpose). When I apply this eval band aid, Carp reports the real error instead of the useless error that may never be fixed. The error has something to do with lack of ref counting of the stack. It would be nice if Carp were patched as in the RT ticket, as it restores Carp to being at least somewhat useful when this happens.
Re^2: Stupid question
by flexvault (Monsignor) on May 12, 2012 at 10:32 UTC

    tye,

      #!/usr/bin/perl is the standard place for Perl as declared by Larry himself. Even if you install /usr/local/bin/perl, please also put a link in /usr/bin and please use #!/usr/bin/perl in scripts that you make public

    Please consider in the *nix world of today, you may make your system useless if you do the above. Changing the default system "perl" is quite dangerous. 5 years ago, I would agree, but today it's better to link the other way around if you're not installing a different Perl. Just my 2 cents.

    Thank you

    "Well done is better than well said." - Benjamin Franklin

      All I suggested is that there be a /usr/bin/perl (if there is any version of Perl installed). I don't see how there being a /usr/bin/perl would make a modern Unix system "useless".

      - tye        

        tye,

        I guess I didn't explain myself properly.

        Several of the newer versions of *nix distributions seem to be shipping a vendor updated "safer" Perl in /usr/bin. If you replace this "safer" Perl with a "compiled by you" Perl without the vendor's "patches", many of the system utilities that require the "safer" Perl just don't work.

        So my new rules would be:

        • Never use or touch the /usr/bin/perl
        • Always use a known version of Perl ( best to compile yourself ).
        • Preferred location is /usr/local/bin/perl ( I usually link to the known Perl. )

        This is not what I would like, but it is necessary. In the past 2 years, I've had to re-install 3 different new distros that after installing a newer Perl as /usr/bin/perl many utilities just don't work. I used to routinely install a new Perl as /usr/bin/perl. I don't do that anymore!
        Note: Sorry to admit I did this 3 times, but old habits are hard to break.

        How many times on PM do you see comments of "...doesn't work...", followed by "...works on my system...". I'm pointing to the difference may be in using the vendor supplied Perl.

        This is not a Perl problem!

        I have said many times that Perl is getting better and better. I have never changed Perl code, nor do I see any need to. When I compile Perl myself, it works as documented.

        Thank you

        "Well done is better than well said." - Benjamin Franklin

      Whichever direction you link it, that would seem to present a problem. If you're installing a separate perl because you want to leave the stock perl pristine for the OS to use, well, the OS will expect to find the stock perl in /usr/bin/perl. If /usr/bin/perl is a link to /usr/local/bin/perl (or wherever), then the OS will be using your local version, so you might as well have just replaced the stock version with your own version, right?

      Another thought: if you symlink /usr/bin/perl to somewhere else, can you trust that an OS upgrade of the stock perl won't clobber your symlink?

      Aaron B.
      Available for small or large Perl jobs; see my home node.