<div dir="ltr">I'd like to propose a change in the behavior of Control.Exception to help guarantee cleanups are not accidentally lost.<div><br></div><div>For example, bracket is defined as:</div><div><pre style="color:rgb(0,0,0)">
<span class="">bracket</span> <span class="">before</span> <span class="">after</span> <span class="">thing</span> <span class="" style="color:red">=</span>
<a name="line-260"></a>  <span class="">mask</span> <span class="">$</span> <span class="" style="color:red">\</span><span class="">restore</span> <span class="" style="color:red">-></span> <span class="" style="color:blue">do</span>
<a name="line-261"></a>    <span class="">a</span> <span class="" style="color:red"><-</span> <span class="">before</span>
<a name="line-262"></a>    <span class="">r</span> <span class="" style="color:red"><-</span> <span class="">restore</span> <span class="" style="color:red">(</span><span class="">thing</span> <span class="">a</span><span class="" style="color:red">)</span> <span class="">`onException`</span> <span class="">after</span> <span class="">a</span>
<a name="line-263"></a>    <span class="" style="color:blue">_</span> <span class="" style="color:red"><-</span> <span class="">after</span> <span class="">a</span>
<a name="line-264"></a>    <span class="">return</span> <span class="">r</span></pre></div><div><div>This definition has a serious problem: "after a" (in either the exception handling case, or the ordinary case) can include interruptible actions which abort the cleanup.</div>
<div><br></div><div>This means bracket does not in fact guarantee the cleanup occurs.</div><div><br></div><div>For example:</div><div><br></div><div>readMVar = bracket takeMVar putMVar -- If async exception occurs during putMVar, MVar is broken!</div>
<div><br></div><div>withFile .. = bracket (openFile ..) hClose -- Async exception during hClose leaks the file handle!</div><div><br></div><div>Interruptible actions during "before" are fine (as long as "before" handles them properly).  Interruptible actions during "after" are virtually always a bug -- at best leaking a resource, and at worst breaking the program's invariants.</div>
<div><br></div><div>I propose changing all the cleanup handlers to run under uninterruptibleMask, specifically:</div><div><br></div><div><b>bracket, bracketOnError, bracket_, catch, catchJust, finally, handle, handleJust, onException</b></div>
<div><b><br></b></div><div>should all simply wrap their exception/cancellation handler with uninterruptibleMask.</div><div><br></div><div>The danger of a deadlock is minimal when compared with the virtually guaranteed buggy incorrect handling of async exceptions during cleanup.</div>
<div><br></div>-- <br><div dir="ltr">Eyal</div>
</div></div>