haskell / haskeline

A Haskell library for line input in command-line programs.
https://hackage.haskell.org/package/haskeline
BSD 3-Clause "New" or "Revised" License
223 stars 75 forks source link

`runInputT` crashes when executed in more than one thread #177

Open jberthold opened 1 year ago

jberthold commented 1 year ago

The following program crashes with low-level memory errors (seg.fault, double-free, ...) when executed with more than one OS thread.

module Main where
import Control.Concurrent (forkIO, threadDelay)
import System.Console.Haskeline (runInputT, defaultSettings)

main :: IO ()
main = do
    forkIO inputT
    forkIO inputT
    threadDelay 1
  where
    inputT = runInputT defaultSettings $ pure ()
jost@freshcode-1:~/work/RV/code/scratch/haskeline-issue-ghc-927$ ghc-9.2.7 -package haskeline crashMe.hs -o crashMe -threaded -with-rtsopts "-N2"
jost@freshcode-1:~/work/RV/code/scratch/haskeline-issue-ghc-927$ while ./crashMe; do echo "worked, again"; done 
free(): double free detected in tcache 2
Aborted (core dumped)
jost@freshcode-1:~/work/RV/code/scratch/haskeline-issue-ghc-927$ while ./crashMe; do echo "worked, again"; done 
worked, again
worked, again
worked, again
worked, again
worked, again
worked, again
Segmentation fault (core dumped)
jost@freshcode-1:~/work/RV/code/scratch/haskeline-issue-ghc-927$ 

Is this expected (i.e., is haskeline's InputT known to not be thread-safe?

The issue happens for us when running unit tests in parallel so we can work around it, but it is somewhat ugly how it fails.

bgamari commented 1 year ago

My guess is that this is due to the fact that Haskeline is implemented using the Haskell terminfo library, which is itself implemented in terms of the non-thread-safe ncurses library.