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

This is the first time I've used an END block. I need its functionality because I call 'die' at several points throughout this program and I have to always perform the code in the END block.

I was making the final edits to a program's usage() function and noticed the following warnings following a --help invocation:

perl -w ks.pl -h
Use of uninitialized value $time in concatenation (.) or string at ks. +pl line 253. Use of uninitialized value in concatenation (.) or string at ks.pl lin +e 258. Use of uninitialized value in concatenation (.) or string at ks.pl lin +e 258. Use of uninitialized value in concatenation (.) or string at ks.pl lin +e 258. Use of uninitialized value in concatenation (.) or string at ks.pl lin +e 258. Character in 'c' format wrapped in pack at ks.pl line 262. Use of uninitialized value $time in concatenation (.) or string at ks. +pl line 283.

Ah so! (German for "I see!") -- these warnings were the result of the END block being (unconditionally) executed after the usage() function.

While I understand why this is happening, my question is: is there a way to have an unconditional END block execute except when the program's usage() function is being invoked? If not, then I propose to create yet another function to be called prior to die()'ing that will execute what's presently in the END block.

Here's the relevant code:

#!/usr/bin/perl -w use strict; use Getopt::Std; ... # Don't want END block to execute when these are invoked: sub HELP_MESSAGE(); # getopts() --help automatically invokes VERSIO +N_MESSAGE() first sub VERSION_MESSAGE(); # getopts() supports arguments --version and -- +help sub usage(); ... INIT { $| = 1; # Make Getopt::Std exit after printing # VERSION_MESSAGE() and/or HELP_MESSAGE() $Getopt::Std::STANDARD_HELP_VERSION = 1; } ...By design, main-line code comes to this END block: # An END block is always executed (barring some exceptions) as # late as possible, even after die() is called END { export_to_file_csv(); export_to_storable(); warn "Pages : $pages of Total Pages: $total_pages"; warn "Projs : $projs of Total Projs: $total_projs"; warn sprintf ("Images: %d amounting to bytes: %s", $imgs, $bytes)); } # END OF PROGRAM (normal or otherwise).

I thank you for your time and assistance.

Searched for donut and crumpit. Found donate and stumbit instead.

Replies are listed 'Best First'.
Re: Want END block to run except when usage()/--help invocation
by BrowserUk (Patriarch) on Feb 27, 2015 at 05:39 UTC

    One way would be to set a flag in your usage() func and then bracket the code in the end block with: unless( $flag ) { ... }

    Another would be to use POSIX::_exit() which will bypass END blocks (and other other cleanup including DESTROY funcs).


    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority". I'm with torvalds on this
    In the absence of evidence, opinion is indistinguishable from prejudice. Agile (and TDD) debunked

      Thank you for this useful info.

      It also made me think of this question: Is there a way to dynamically disable 'use strict' and/or 'use warnings' at run-time?

      E.g. either entirely, or perhaps for a block:

      ... # disable 'use strict' and/or 'use warnings' do_some_code_known_to_cause_warnings(); # re-enable 'use strict' and/or 'use warnings' ...
      Searched for donut and crumpit. Found donate and stumbit instead.

        Is there a way to dynamically disable 'use strict' and/or 'use warnings' at run-time?

        Do not use the -w switch then, use warnings instead: # <- edited, see BrowserUK's correct comment below.

        use strict; use warnings; # ... no strict; no warnings 'uninitialized'; # only specific warnings switched off. # un-refined code use warnings 'uninitialized'; # escape to safety use strict;

        You don't need to switch off strict for the case in question, though.

        Cheers, Sören

        Créateur des bugs mobiles - let loose once, run everywhere.
        (hooked on the Perl Programming language)

        You can use the no strict or no warnings pragmas. It is usually better to disable only some of the strictures or of the warnings, for example:
        no strict 'vars'; no warnings 'recursion';
        and only for a limited scope.

        Update: fixed wrong formatting tags.

        Je suis Charlie.

        That's another way to go, provided that the code with the warnings doesn't do anything permanent, like write to a file.

        (But then, I wonder at the purpose of an END block that doesn't do anything permanent?)


        With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority". I'm with torvalds on this
        In the absence of evidence, opinion is indistinguishable from prejudice. Agile (and TDD) debunked
Re: Want END block to run except when usage()/--help invocation
by Anonymous Monk on Feb 28, 2015 at 01:01 UTC
    I suggest you trap the exception ("die" ...) with an eval { } block within your code, maybe in an outer level subroutine that simply calls an inner sub to do the actual work. I would not rely on the END-block per se.