[Haskell-cafe] Conduit Error Output: Control.Monad.Trans.Resource.stateCleanup

Lyndon Maydwell maydwell at gmail.com
Tue Feb 21 08:57:14 CET 2012


Hi Michael,


The behaviour of my original code has now changed to output nothing
with no errors. I'm not sure of the significance of this as my code
was incorrect, however, using the code you demonstrated gives the
desired results.

Thanks for the blindingly quick response!


On Tue, Feb 21, 2012 at 3:30 PM, Michael Snoyman <michael at snoyman.com> wrote:
> On Tue, Feb 21, 2012 at 7:40 AM, Michael Snoyman <michael at snoyman.com> wrote:
>> On Tue, Feb 21, 2012 at 5:46 AM, Lyndon Maydwell <maydwell at 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



More information about the Haskell-Cafe mailing list