[Haskell-cafe] unexpected behavior / bug in try .
bertram.felgenhauer at googlemail.com
Mon Jan 18 13:04:54 EST 2010
A late reply - but as far as I can see, this has gone unanswered so far.
Thomas Hartman wrote:
> Currently try . System.FilePath.Find.findWithHandler
(from the FileManip package, I guess)
> will return an exception wrapped in Right, which seems Wrong. For sure
> it will just get ignored if wrapped in an ErrorT computation and I
> suspect this could lead to other glitchy/unexpected behavior when used
> in sysadmin scripts.
The short answer is that lazy IO and exceptions don't mix. As the
documentation says, findWithHandler returns a list lazily. Lazy IO
is (usually) implemented using unsafeInterleaveIO.
The 'try' in 'try . System.FilePath.Find.findWithHandler' has no effect
after the findWithHandler function returns - which happens immediately
after testing whether the given root path is a directory.
Now when an error occurs - that happens when the code examines the
resulting list from findWithHandler - your exception handler (abort) is
executed by findWithHandler, which in your case will raise another
exception. This exception will be raised in the context of the code
processing the list - and there is no 'try' in effect there.
You can avoid that problem by either making IO strict, or by providing
a handler that does not raise any exceptions.
> Possible fix: you get the expected behavior if you remove
> unsafeInterleaveIO from System.FilePath.Find.findWithHandlers
Right. That will make findWithHandlers use strict IO, and exceptions
will work as expected. On the downside, you'll now read in the whole
directory tree into memory before processing it.
Do we have an Iterat(or|ee) implementation of directory traversal?
More information about the Haskell-Cafe