Skip to content

Stack overflow due to unsafePerformIO

The following program, extracted from a utf8 decoder for ByteStrings, overflows the stack when run with rules on. Speaking to SimonM, this is due to the stack squeezing optimisation not working for unsafePerformIO, meaning the resulting loop actually uses up stack.

import qualified Data.ByteString.Char8 as S 

main = putStrLn $ filter (\x -> enc x /= [x]) list
  where list = ['\0'..'\x10ffff'] ++ ['\0'..'\10']

{-# NOINLINE enc #-}
enc :: Char -> String
enc x = S.singleton x `seq` [x]

After fusing and optimising, S.singleton here is allocated using unsafePerformIO to wrap the allocation, and seems to run out of stack.

However, I've confirmed this code does work if its changed to use unsafeDupablePerformIO.

I'm filing this ticket to get documentation on what is going on here, so we can have something to point to if it comes up again, and to clarify that unsafeDupablePerformIO is the correct fix.

SimonM, could you summarise what the issue is?

Trac metadata
Trac field Value
Version 6.8.2
Type Bug
TypeOfFailure OtherFailure
Priority normal
Resolution Unresolved
Component Runtime System
Test case
Differential revisions
BlockedBy
Related
Blocking
CC dons@galois.com
Operating system Unknown
Architecture Unknown
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information