Exception handling in GHC

Dean Herington heringto@cs.unc.edu
Fri, 24 Jan 2003 18:58:14 -0500 (EST)


On Fri, 24 Jan 2003, Sarah Thompson wrote:

> I've noticed some interesting behaviour:
> 
> Prelude Control.Exception> try (return (error "e"))
> Prelude Control.Exception> it
> Right *** Exception: e
> 
> It would appear that when the result of this function is evaluated, the
> exception fires during evaluation, after the try is out of scope. I suppose
> it makes some kind of twisted sense due to lazy evaluation going on, but it
> is certainly a gotcha.
> 
> I did notice this:
> 
> Prelude Control.Exception> try (return $! (error "e"))
> Prelude Control.Exception> it
> Left e
> 
> Seemingly, forcing strict evaluation on the argument of return fixes the
> problem by making sure that any exception that *can* happen, *does* happen.
> 
> However, this code from my COM wrapper:
> 
> --[id(3)] HRESULT XmlQuery([in,string] BSTR query, [out,retval]BSTR* xml);
> xmlQuery :: String -> State -> IO String
> xmlQuery qry (State st) = do
>     db <- readIORef st
>     Control.Exception.catch (return $! (XMLDatabase.xmlQuery qry db))
>                             (\ _ -> return "<error description=\"Parse
> error\"/>")
> 
> doesn't work. If XMLDatabase.xmlQuery throws an exception, the COM wrapper
> still terminates the host application (Yes, Sigbjorn - I did apply your
> patch to HDirect, but it seemed to make no difference).

Your COM wrapper code probably behaves differently because the error is
not evoked at the very top level.  Note that `seq` (and hence ($!)) only
force evaluation to "weak head normal form", which essentially means only
enough to determine the top-level constructor.  You may need to evaluate
more deeply.  Check out `DeepSeq`
(http://haskell.org/pipermail/haskell/2001-August/001586.html) and/or
"strategies"
(http://www.mail-archive.com/haskell@haskell.org/msg09543/Strategies.lhs). 

> I'm still a bit stuck here!
> 
> Sarah

Dean