Skip to content

GHC 8.4.1 regression: segfault when loading doctest on a module with ANNs on Ubuntu 16.04 or later

As observed here, any attempt to run doctest on a module that contains an ANN will result in a segfault—but only under certain settings! To explain better what I mean, let's look at a stripped-down version of doctest:

-- Bug.hs
module Main (main) where

import Control.Applicative ((<|>))
import Control.Monad.IO.Class (liftIO)
import Data.Char (isSpace)
import Data.List (dropWhileEnd)
import Digraph (flattenSCCs)
import GHC (depanal, getSessionDynFlags, guessTarget, loadModule, noLoc,
            parseDynamicFlags, parseModule, runGhc, setSessionDynFlags,
            setTargets, topSortModuleGraph, typecheckModule)
import System.Directory (findExecutable)
import System.Process (readProcess)

getLibDir :: IO FilePath
getLibDir = do
  Just ghcPath <- findExecutable "ghc" <|> findExecutable "ghc-stage2"
  dropWhileEnd isSpace <$> readProcess ghcPath ["--print-libdir"] ""

main :: IO ()
main = do
  libdir <- getLibDir
  putStrLn libdir
  runGhc (Just libdir) $ do
    (dynflags, _, _) <- getSessionDynFlags >>= flip parseDynamicFlags (map noLoc ["-package base"])
    _ <- setSessionDynFlags dynflags
    mapM (`guessTarget` Nothing) ["Foo.hs"] >>= setTargets
    mods <- depanal [] False
    let sortedMods = flattenSCCs (topSortModuleGraph False mods Nothing)
    let f theMod = do liftIO $ putStrLn "Before parseModule"
                      m1 <- parseModule theMod
                      liftIO $ putStrLn "Before typecheckModule"
                      m2 <- typecheckModule m1
                      liftIO $ putStrLn "Before loadModule"
                      m3 <- loadModule m2
                      liftIO $ putStrLn "After loadModule"
                      return m3
    mods' <- mapM f sortedMods
    mods' `seq` return ()

As well as a module with an ANN:

module Foo where

{-# ANN module "I'm an annotation" #-}

If you attempt to compile and run Bug.hs with GHC 8.2.2, everything is fine and dandy:

$ PATH=/opt/ghc/8.2.2/bin:$PATH ghc -fforce-recomp Bug.hs -package ghc
[1 of 1] Compiling Main             ( Bug.hs, Bug.o )
Linking Bug ...

$ PATH=/opt/ghc/8.2.2/bin:$PATH ./Bug 
/opt/ghc/8.2.2/lib/ghc-8.2.2
Before parseModule
Before typecheckModule
Before loadModule
After loadModule

But if these two criteria are met:

  • You're using GHC 8.4.1-alpha
  • You're using Ubuntu 16.04 or later

Then this will result in a segfault!

$ PATH=/opt/ghc/8.4.1/bin:$PATH ghc -fforce-recomp Bug.hs -package ghc
[1 of 1] Compiling Main             ( Bug.hs, Bug.o )
Linking Bug ...

$ PATH=/opt/ghc/8.4.1/bin:$PATH ./Bug 
/opt/ghc/8.4.1/lib/ghc-8.4.0.20171222
Before parseModule
Before typecheckModule
Segmentation fault (core dumped)

$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 17.04
Release:        17.04
Codename:       zesty

The second criteria about Ubuntu version is the most baffling part, but the segfault does not appear to occur when I try it on, for instance, an Ubuntu 14.04 machine:

$ PATH=/opt/ghc/8.4.1/bin:$PATH ghc -fforce-recomp Bug.hs -package ghc
[1 of 1] Compiling Main             ( Bug.hs, Bug.o )
Linking Bug ...

$ PATH=/opt/ghc/8.4.1/bin:$PATH ./Bug 
/opt/ghc/8.4.1/lib/ghc-8.4.0.20171222
Before parseModule
Before typecheckModule
Before loadModule
After loadModule

$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 14.04.5 LTS
Release:        14.04
Codename:       trusty
Trac metadata
Trac field Value
Version 8.4.1-alpha1
Type Bug
TypeOfFailure OtherFailure
Priority highest
Resolution Unresolved
Component GHC API
Test case
Differential revisions
BlockedBy
Related
Blocking
CC
Operating system
Architecture
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information