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

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

What's the difference between use warnings and use warnings FATAL => 'all'? What's the rationale for using the latter instead of the former? And where are the differences between the two uses documented?

I'm asking these questions because, within the last year or so, I've seen a lot of instances on PerlMonks and Stack Overflow where someone uses use warnings FATAL => 'all' in place of the more often-recommended, canonical and simpler use warnings.

Jim

Replies are listed 'Best First'.
Re: Difference Between use warnings and use warnings FATAL => 'all'
by Athanasius (Archbishop) on Dec 27, 2013 at 02:32 UTC

    The difference is in the way the script behaves after the warning is issued: with use warnings; the script continues as normal, but with use warnings FATAL => 'all'; (note the spelling: warnings must be plural here) the script dies immediately:

    12:30 >perl -e "printf qq[%f\n], $x;" 0.000000 12:31 >perl -e "use warnings; printf qq[%f\n], $x;" Name "main::x" used only once: possible typo at -e line 1. Use of uninitialized value $x in printf at -e line 1. 0.000000 12:31 >perl -e "use warnings FATAL => 'all'; printf qq[%f\n], $x;" Name "main::x" used only once: possible typo at -e line 1. Use of uninitialized value $x in printf at -e line 1. 12:31 >

    This is documented in perllexwarn#Fatal-Warnings.

    As to why? Well, in a long script with a lot of output, it may be easy to overlook warnings when they are interlaced with other information. Forcing the script to die at the point where the warning is detected makes it easier to locate and identify the problem, and motivates the programmer to fix the warning earlier, rather than later! (There may be other reasons.)

    Hope that helps,

    Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

Re: Difference Between use warnings and use warnings FATAL => 'all'
by davido (Cardinal) on Dec 27, 2013 at 04:01 UTC

    It's always use warnings, sometimes just use warnings, and other times use warnings FATAL => 'all';, which is the same as use warnings qw( FATAL all );... just a cooler way of typing it.

    One of the best ways to prevent bugs from creeping into a program is to write it with as much "questionable behavior" or "questionable practice" detection enabled as possible. This is why C compilers have strict modes, why Perl has strict, and so on. FATAL => all elevates to the level of throwing an exception when a warning occurs. It's like saying, "I want warnings to be exceptional situations." Stop everything, hold the horses, go directly to jail, do not pass go ----- we need to fix this!

    There are times where STDERR is routed to a log file, where it won't be immediately seen by the developer or maintainer unless he goes looking for it. Perhaps it gets buried behind a bunch of other stuff that isn't relevant, and it becomes hard to determine the context under which the warning occurred. By stopping the run immediately, nothing else (or very little else) will be in the log. Context becomes more readily apparent.


    Dave

      This is why C compilers have strict modes,

      I believe this is the direct equivalent of strict/warnings-FATAL-all

      gcc -ansi -pedantic -Wall -Wextra ...

        gcc -ansi -pedantic -Wall -Wextra ...
        No, it's worse:
        gcc <various-warning-flags> -Wfatal-errors
        i.e. it stops at the first warning. In practice, this means that you get to fix/suppress the first warning your program causes, then start it over again to fix/suppress the second, etc., rather than getting a list of all of them and deciding what to do.
Re: Difference Between use warnings and use warnings FATAL => 'all'
by LanX (Saint) on Dec 27, 2013 at 07:11 UTC
    In simple terms: "fatal all" means all errors¹ warning-events die!

    The other questions have been answered.

    Cheers Rolf

    ( addicted to the Perl Programming Language)

    ¹) see following discussion

      At the risk of being a little pedantic LanX, your assertion isn't quite correct in this context - fatal => all actually means that all warnings (c/w errors as you claim) result in a script die'ing.

      A user level that continues to overstate my experience :-))
        Well I was aware of that, but since I identified only two categories of error-exceptions (signals), "dieing" and "warning", I was sure that my assertion was right. (all of them die after fatal-all)

        Now at second thought I remember all these special variables (e.g. $!, $@, $^E, $? ...) holding silent external error messages needed to be actively read and processed.

        (like in open ... or die "Terminating because $!";)

        Here you are of course right, those "errors" do not die.

        Corrected, thanks. :)

        Cheers Rolf

        ( addicted to the Perl Programming Language)

Re: Difference Between use warnings and use warnings FATAL => 'all'
by BrowserUk (Patriarch) on Dec 27, 2013 at 12:39 UTC

    I've always thought of fatal warnings being akin to your car engine cutting out and the brakes being applied automatically when the fuel-low warning light comes on.

    The warning light serves the purpose of giving you a chance to avoid getting stranded.

    Making warnings fatal definitely strands you; and could be literally fatal if you are in the outside lane at speed when the fuel-low light comes on.

    There is a difference between warnings and errors; and treating them both the same is like treating gangrene and a paper cut equally with amputation.

    The former might lead to the latter eventually; but it is a rare occurrence. Another instance of dogma trumping logic.


    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".
    In the absence of evidence, opinion is indistinguishable from prejudice.

      It really depends on the condition that the warning/error is catching.

      For "low fuel", a dashboard light is better than switching off the engine. For "driver has fallen asleep with foot on the accelerator pedal", stopping the car might be a better solution.

      If an undef in a variable would led you to deleting every row in a database table, it might be better for the uninitialized warning to be fatal.

      Whether a warning can be detected at compile time is another important consideration. Having an unimportant condition cause a long-running process to crash can be awful, but if the same warning prevented it from being started, that would be OK, because it could be fixed straight away. For example, the "void" and "once" warnings categories are detected at compile time, while "numeric" and "uninitialized" are detected at run time.

      use Moops; class Cow :rw { has name => (default => 'Ermintrude') }; say Cow->new->name
        For "driver has fallen asleep with foot on the accelerator pedal", stopping the car might be a better solution.

        Not really. Wind down the window; play music loud; vibrate the seat or steering wheel; a strident bonging sound; all would be preferable to bringing the car to a sudden halt in the middle of a motorway.

        If an undef in a variable would led you to deleting every row in a database table, it might be better for the uninitialized warning to be fatal.

        It's hard for me to imagine how that would occur, but if it is a possibility, then I might resort to use warnings FATAL => 'uninitialized'; within some limited scope(s); but never FATAL => 'all'.

        I routinely eliminate/guard against all warnings in my code as I go along; but when they do occur unexpectedly, seeing whether they are 1-offs or repeated, whether once they start, they persist or are occasional transients; and where the code goes and what other knock-on warnings arise as a result; all assist in the postmortem of working out what went wrong and what to do about it.

        Even more so when, for example, you get an unhandled transient warning induced by bad data in a long-running, unattended process.


        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".
        In the absence of evidence, opinion is indistinguishable from prejudice.
        If an undef in a variable would led you to deleting every row in a database table, it might be better for the uninitialized warning to be fatal.
        This is why you put in thorough sanity checks before doing something so destructive:
        if (defined $thing) { destroy_database($thing); } else { do_something_else(); }
        undef has well-defined semantics in Perl (empty or zero), which are very useful in most cases. You should know when your code may do something catastrophic, and be very careful then, but that's no reason to be paranoid everywhere.

      That was a dramatic way to put it, but this does largely sum up why I prefer to use warnings during development but drop it when the code moves to production.

      The users should not have to see Perl underwear, and are not expected to understand what they see anyway. But a developer should code until the warnings subside for all test cases, which should be fairly encompasing if you are using Test-Driven Development.

      Turning the warnings fatal is in interesting escalation of the issue. I'm not sure I see the point for the vast majority of development, but then I trust that if I tell my developers to code with warnings on until none appear that they will do so.

      I suppose I could imagine a corner case where recovery from bade code might be a huge inconvenience or take an inordinate amount of time. If the routine, for example, might risk deleting every row in a table and that would halt work by lots of developers or the restore might take a huge amount of time. But there are usually other ways to mitigate these kinds of problems, so I'm still not sure I buy into this approach to solve this kind of problem.

      I could see one developer turning warnings fatal because they are the type who wants to fix the warning as soon as they bump into it, so this makes a one-line way to force the code to stop immediately so the errant code can be adjusted. And then perhaps forgetting to remove it before checking the code back in to source control. Such a situation could cause another developer to suddenly start seeing lots of warnings->FATAL references, I suppose.

      I would be inclined to make checking for that a step during the process by which code is promoted into production. Especially since I am a proponent of the no-warnings-in-production philosophy anyway, this would automatically be caught in that net.

      But I find it terribly rude to force end users to see error messages which are not generated in a context they are expected to understand. They are not likely to be computer scientists or software engineers, and may not even like the "{explitive deleted} computer" in the first place. The last thing we need to be doing is showing them error messages they cannot hope to understand, did not cause, and which were generally designed for us computer geeks to see.

      Have mercy on the user. Ultimately, they pay our salary.

      There is a difference between warnings and errors; and treating them both the same is like treating gangrene and a paper cut equally with amputation.

      It's worse than that. p5p is cautious about adding exceptions for previously working code, at least without requiring users to use the feature pragma or an explicit version number. p5p is much more willing to add warnings where they did not exist before.

      Code which unilaterally converts warnings to exceptions could find itself dying of exceptions when run on a new release of Perl, whereas code which enables warnings would (merely) add to the warning logs. That's a risk I'm not willing to take for most code.

      Edit to add: I know BuK already knows everything I wrote, but his message was the best place to put this reminder for everyone else.

        Edit to add: I know BuK already knows everything I wrote,

        Knowing (somewhere, deep down; maybe) and having thought about the consequences are two different things.

        I stand as a one of those gratefully reminded. Thank you.


        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".
        In the absence of evidence, opinion is indistinguishable from prejudice.
Re: Difference Between use warnings and use warnings FATAL => 'all'
by Anonymous Monk on Dec 27, 2013 at 02:31 UTC

      …and?

        …and?

        and it explains the difference?

Re: Difference Between use warnings and use warnings FATAL => 'all' (debugging)
by LanX (Saint) on Dec 29, 2013 at 08:18 UTC
    > What's the rationale for using the latter instead of the former?

    I'm surprised nobody mentioned till now, but personally, I use it from time to time for debugging.

    If warnings get messy, it's easier to handle them one by one. (not necessarily => all warnings)

    YMMV =)

    Cheers Rolf

    ( addicted to the Perl Programming Language)

      For debugging purposes, I was very happy to learn the following:

      $SIG{__WARN__} = sub { print $_[0]; $DB::single = 1 };

      I was annoyed to notice that warning messages did not appear as I was running code in the debugger. That might be fixable; I have never looked into it. This statement is now included in just about any program I write of any length. Not only does it give me the message but stops the debugger at the point of warning.

      I comment out the line when not running in the debugger because it generates a warning message. What irony.

        Thanks, personally I rarely use the debugger for debugging, at least not with code I wrote.

        :)

        To see warnings with perl -d you could try using it from an IDE like emacs to separate output frame from debugging GUI.

        update

        First I have to say that I don't have the problem that warnings aren't shown in my debugger-instance, but I tweaked a lot in the past. Anyway ...

        > I comment out the line when not running in the debugger because it generates a warning message.

        ... you could put that code into debugger's rc-file '.perldb' or into PERL5DB environment variable to make it the default behavior of the debugger.

        Like that you don't need to change the scripts. =)

        update

        this works for me

        lanx@nc10-ubuntu:$ cat .perldb sub afterinit { $SIG{"__WARN__"}= sub { print "$_[0]"; $DB::single=1 }; }

        see perldebug for details

        Cheers Rolf

        ( addicted to the Perl Programming Language)

Re: Difference Between use warnings and use warnings FATAL => 'all'
by Anonymous Monk on Dec 27, 2013 at 15:02 UTC
    I see this used in "unattended programs that do Really Important Thing$$$$." When you absolutely know that the program should not encounter the slightest hiccup, such that you want the program to die when and if it does so. There is no "goodness vs. badness" to this, I think. It's simply another Perl feature that is there if you need it, and perhaps unknown to you if you don't (yet). Perl, being a very pragmatic tool, is loaded with features like that.