
On Tue, Feb 21, 2012 at 7:40 AM, Michael Snoyman
On Tue, Feb 21, 2012 at 5:46 AM, Lyndon Maydwell
wrote: Hi Michael, Café.
I'm writing some code using the conduit library and am encountering the following error output (while the program appears to function correctly) when using Data.Conduit.Lazy.
The error given is:
profile_simple_test_data: Control.Monad.Trans.Resource.stateCleanup: There is a bug in the implementation. The mutable state is being accessed after cleanup. Please contact the maintainers.
A reduced code snippet that generates this error is (also attached):
import Control.Monad import System.Environment import Control.Monad.IO.Class (liftIO) import System.IO import Data.Conduit.Lazy import Data.List (sort)
import Data.Conduit
import Prelude hiding (map)
main = getArgs >>= process
process args = mapM_ sorted args
sorted x = runResourceT (lazyConsume $ sourceFeed x) >>= (mapM_ print . id)
sourceFeed :: ResourceIO m => FilePath -> Source m String sourceFeed file = sourceIO (openFile file ReadMode) hClose (\h -> liftIO $ do eof <- hIsEOF h if eof then return IOClosed else fmap IOOpen $ hGetLine h)
when run over any text file.
I may be doing something inconsistent with the correct use of sourceIO or lazyConsume, however, I tried to follow the example at http://www.yesodweb.com/home/snoyberg/blogs/conduit/conduit/source/source.di... as closely as possible.
Is this a bug, or simply an incorrect use of Conduit?
I haven't fully debugged this yet. There's certainly a bug in the implementation of ResourceT, but the sample program is also wrong. You can't pass the result from a call to lazyConsume outside the scope of its ResourceT; the correct way to write sorted would be:
sorted x = runResourceT $ lazyConsume (sourceFeed x) >>= mapM_ (liftIO . print)
My guess is that this is a fallout from the transition away from mutable variables: lazyConsume no longer has any way of knowing that its ResourceT has already been terminated. Perhaps a simple solution would be to expose a primitive that checks if the ResourceT block has already been finalized.
Michael
I've added a test case for this bug, and fixed it. The commit is: https://github.com/snoyberg/conduit/commit/87e890fe7ee58686d20cabba15dd37f18... The basic idea is to add an extra constructor to represent when the ResourceT has already been closed, and expose a function resourceActive to check the state. Can you check if this solves your problem? Michael