[Haskell-cafe] threads + IORefs = Segmentation fault?

David Roundy droundy at darcs.net
Fri Jan 18 18:22:55 EST 2008

Hi all,

I'm working on some new progress-reporting code for darcs, and am getting
segmentation faults!  :( The code uses threads + an IORef global variable
to do this (with lots of unsafePerformIO).  So my question for the gurus
who know more about this than I do:  is this safe? I thought it would be,
because only one thread ever modifies the IORef, and the others only read
it.  I don't really care if they read a correct value, as long as they
don't segfault.

The code (to summarize) looks like:

{-# NOINLINE _progressData #-}
_progressData :: IORef (Map String ProgressData)
_progressData = unsafePerformIO $ newIORef empty

updateProgressData :: String -> (ProgressData -> ProgressData) -> IO ()
updateProgressData k f = when (progressMode) $ modifyIORef _progressData (adjust f k)

setProgressData :: String -> ProgressData -> IO ()
setProgressData k p = when (progressMode) $ modifyIORef _progressData (insert k p)

getProgressData :: String -> IO (Maybe ProgressData)
getProgressData k = if progressMode then lookup k `fmap` readIORef _progressData
                                    else return Nothing

The key function is

beginTedious :: String -> IO ()
beginTedious k = do tid <- forkIO $ handleProgress k
                    debugMessage $ "Beginning " ++ k
                    setProgressData k $ ProgressData { sofar = 0,
                                                       latest = Nothing,
                                                       total = Nothing,
                                                       handler = Just tid }

which is called before an action that may be so tedious for our users that
they need their day brightened by messages such as "Applying patch
137/1436".  The handleProgress function alternates between threadDelay and
reading the progress data to see whether any progress has been made and
printing messages.  Meanwhile the main thread calls functions that update

Anyhow, the point is that I'm getting segfaults, even after recompiling
everything from scratch! Is this in fact that unsafe? Do I really need to
switch to MVars, even though no locking is required?
David Roundy
Department of Physics
Oregon State University

More information about the Haskell-Cafe mailing list