On Tue, Feb 21, 2012 at 7:40 AM, Michael Snoyman <mich...@snoyman.com> wrote: > On Tue, Feb 21, 2012 at 5:46 AM, Lyndon Maydwell <maydw...@gmail.com> 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.ditamap?nav=nav-2 >> 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/87e890fe7ee58686d20cabba15dd37f18ba66620 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 _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe