I have a function that I fork off into a thread using forkIO. The function runs in a ReaderT monad transformer so that I can pass in a read-only configuration record:
main :: IO ()
main = do
...
forkIO $ runReaderT watcher config
The watcher
function watches an MVar using tryTakeMVar (I don't want it to block.) The MVar is stored in the config and is called "drawer" because it behaves like a transaction drawer between main
and the thread that watcher
is watching in, basically a skip channel.
printThing
has a signature of printThing :: Thing -> ReaderT Config IO ()
and calls putStrLn
to print a Thing
.
watcher :: ReaderT Config IO ()
watcher = do
cfg <- ask
mNewThing <- liftIO $ tryTakeMVar $ drawer cfg
case mNewThing of
Nothing -> do
--liftIO $ putStr "" -- uncommenting this helps
watcher
Just newThing -> do
printThing newThing
watcher
The problem is that the program hangs when it runs. It seems to be stuck in a loop. Calling putStr ""
in main
doesn't help, HOWEVER, calling putStr ""
inside watcher
does trigger the thread -- it starts spinning and printing out Thing
s as expected.
All I can figure is that I'm getting bitten by laziness, but I'm not sure where. I've tried using $!
where possible.
I do IO actions in certain conditions of watcher
, but not all of them. Is that the problem? I need to do IO actions in ALL conditions branches?
If it helps, I didn't have this problem before I wrapped everything up in the ReaderT
transformer. I was just passing config
around as an argument.