How to find floating point exceptions in Haskell?

Suppose a large and complex Haskell program produces NaN time at runtime. How do I find where in my code this happened without spending a lot of time adding a lot of NaN checks to my code? I'm only interested in debugging, so I don't care about portability or performance.

This was discussed five years ago at the Haskell Cafe. A possible solution was proposed, but was not discussed further. https://mail.haskell.org/pipermail/haskell-cafe/2011-May/091858.html

The following is my attempt to get the stack trace to the point where NaN is created (in a small sample program) using feenableexcept, as suggested in the Haskell-cafe discussion:

-- https://www.gnu.org/software/libc/manual/html_node/Control-Functions.html
foreign import ccall "feenableexcept" enableFloatException :: Int -> IO Int

allFloatExceptions :: Int
allFloatExceptions = 1 {-INVALID-} + 4 {-DIVBYZERO-} + 8 {-OVERFLOW-} + 16 {-UNDERFLOW-}

main :: IO ()
main = do
  _ <- enableFloatException allFloatExceptions

  print $ (0/0 :: Double)

Unfortunately, running this code does not create a stack trace :(

$ ghc -rtsopts -prof -fprof-auto testNaN.hs && ./testNaN +RTS -xc
[1 of 1] Compiling Main             ( testNaN.hs, testNaN.o )
Linking testNaN ...
Floating point exception (core dumped)

( ), , GHC , . , installHandler System.Posix.Signals, GHC:

import qualified System.Posix.Signals as Signals

-- https://www.gnu.org/software/libc/manual/html_node/Control-Functions.html
foreign import ccall "feenableexcept" enableFloatException :: Int -> IO Int

allFloatExceptions :: Int
allFloatExceptions = 1 {-INVALID-} + 4 {-DIVBYZERO-} + 8 {-OVERFLOW-} + 16 {-UNDERFLOW-}

catchFloatException :: IO ()
catchFloatException = error "print stack trace?"

main :: IO ()
main = do
  _ <- enableFloatException allFloatExceptions
  _ <- Signals.installHandler Signals.floatingPointException (Signals.Catch catchFloatException) Nothing

  print $ (0/0 :: Double)

, - : (

$ ghc -rtsopts -prof -fprof-auto testNaN.hs && ./testNaN +RTS -xc
[1 of 1] Compiling Main             ( testNaN.hs, testNaN.o )
Linking testNaN ...
testNaN: too many pending signals

. .

$ ghc -rtsopts -prof -fprof-auto -threaded testNaN.hs && ./testNaN +RTS -xc -N2
[1 of 1] Compiling Main             ( testNaN.hs, testNaN.o )
Linking testNaN ...
testNaN: lost signal due to full pipe: 8

testNaN: lost signal due to full pipe: 8

testNaN: lost signal due to full pipe: 8

... repeat many many times, very very fast

, . http://pastebin.com/u3u2cnHE

? , ?

+4

Source: https://habr.com/ru/post/1653854/


All Articles