Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw

FPE not deferred in 5.36

by choroba (Cardinal)
on May 31, 2022 at 13:57 UTC ( #11144315=perlquestion: print w/replies, xml ) Need Help??

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

As you've probably noticed, Perl 5.036 is out.

While reading its delta (to decide what changes need to be done to Syntax::Construct), I noticed the following paragraph:

SIGFPE no longer deferred

Floating-point exceptions are now delivered immediately, in the same way as other "fault"-like signals such as SIGSEGV. This means one has at least a chance to catch such a signal with a $SIG{FPE} handler, e.g. so that die can report the line in perl that triggered it.

I tried to come up with code that triggers the Floating Point E{xception/rror} but I couldn't find any.

local $SIG{FPE} = sub { die "SIGNAL @_" }; my $x = 0; print 2 / $x;

I tried with sqrt -1, no difference. I asked on IRC and was given an example with Inline::C, but even that doesn't behave differently in the new Perl version:

#!/usr/bin/perl use warnings; use strict; use Inline 'C' => <<'__C__'; float killme() { volatile float f = 0.0; volatile float c = f / f; return c; } __C__ local $SIG{FPE} = sub { die "SIGNAL @_" }; print killme();

Can anyone provide an example that shows how the FPE signal is emitted and how its trapping is different in 5.36?

map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]

Replies are listed 'Best First'.
Re: FPE not deferred in 5.36
by haj (Priest) on May 31, 2022 at 14:58 UTC

    I ran into a FPE once.... and while I've not dug into the details, I can give a somewhat dirty way to reproduce it. It is dirty because the bug causing the FPE has been fixed since then. Here's the code:

    $SIG{FPE} = sub { die "Ooops\n" }; use List::Util 'product'; print product(-1,1);

    If you run this in vanilla Perl 5.34 or older without a signal handler, it dies with Floating point exception. If you include the handler like I did, you'll get:

    Maximal count of pending signals (120) exceeded at line 3.

    If you run this in vanilla Perl 5.36, you get the expected result of -1, because the bug (RT139601) has been fixed in that release (in List::Util 1.60, to be precise). But you can catch the FPE by installing an "older" List::Util on top of Perl 5.36:

    cpanm +ls-1.59.tar.gz perl

    This dies with the message Ooops, so in Perl 5.36 the signal handler works as you'd expect.

    Don't forget to upgrade your List::Util after that test :)

      Great, thanks. I'll dig into the older List::Util to see how the error happens, as I don't want to install an older version of a core module in the test suite of Syntax::Construct :-)

      map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
Re: FPE not deferred in 5.36
by hv (Prior) on May 31, 2022 at 15:13 UTC

    Here's the case that caused me to investigate and add this change in the first place:

    % $PERL-5.34.0 -MMath::GMP -wle 'local $SIG{FPE} = sub { die "fpe" }; +$z=Math::GMP->new(1); print $z / 0' Maximal count of pending signals (120) exceeded at -e line 1. fpe at -e line 1. % % $PERL-5.36.0 -MMath::GMP -wle 'local $SIG{FPE} = sub { die "fpe" }; +$z=Math::GMP->new(1); print $z / 0' fpe at -e line 1. %

    The original ticket was Catching SIGFPE. Not sure why my example above isn't reproducing that, but in my real-world code this was stopping me from getting a stack trace to find where the division by zero was occurring.

    Despite the name, this exception is primarily raised for integer division by zero, so the Inline::C example needs s{float}{int}g to show it. See why was sigfpe used for integer arithmetic exceptions for some more detail.

    Perl itself catches these when it performs a division, so you'll only see it from non-perl code linked to your program.

      I can confirm that with ints, it emits "Maximal count of pending signals". It still outputs the line number, as you noted. Probably not worth including into Syntax::Construct, as the change in behaviour is hard to test and the code probably doesn't depend on that (the user debugging the code, though, might well do).

      map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]

        This is rather strange - removing the 'local' stops the die message from showing up:

        % perl-5.34.0 -MMath::GMP -wle 'local $SIG{FPE} = sub { die "divide by + zero" }; $z=Math::GMP->new(1); print $z / 0' Maximal count of pending signals (120) exceeded at -e line 1. divide by zero at -e line 1. % % perl-5.34.0 -MMath::GMP -wle '$SIG{FPE} = sub { die "divide by zero" + }; $z=Math::GMP->new(1); print $z / 0' Maximal count of pending signals (120) exceeded at -e line 1. %

        I don't know why that's occurring. I guess it's possible there's a bug here, but I'm not sure how I might start investigating it. If anything I'd have imagined it working the other way round.

Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://11144315]
Front-paged by davies
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others about the Monastery: (2)
As of 2023-06-09 04:12 GMT
Find Nodes?
    Voting Booth?
    How often do you go to conferences?

    Results (35 votes). Check out past polls.