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
? , ?