<div dir="ltr">No, something like<div><br></div>threadWait :: Event -> Fd -> IO ()<br>threadWait evt fd = do<br> m <- newEmptyMVar<br> mgr <- getSystemEventManager_<br> evt' <- mask_ $ do<br> reg <- registerFd mgr (\_ e -> putMVar m e) fd evt M.OneShot<br> takeMVar m `onException` unregisterFd_ mgr reg<br> if evt' `eventIs` evtClose<br> then ioError $ errnoToIOError "threadWait" eBADF Nothing Nothing<br> else return ()</div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Thu, Jan 17, 2019 at 5:58 PM Michael Walker <<a href="mailto:mike@barrucadu.co.uk">mike@barrucadu.co.uk</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">So, something like this?<br>
<br>
threadWait :: Event -> Fd -> IO ()<br>
threadWait evt fd = do<br>
(m, mgr, reg) <- mask_ $ do<br>
m <- newEmptyMVar<br>
mgr <- getSystemEventManager_<br>
reg <- registerFd mgr (\_ e -> putMVar m e) fd evt M.OneShot<br>
pure (m, mgr, reg)<br>
evt' <- takeMVar m `onException` unregisterFd_ mgr reg<br>
if evt' `eventIs` evtClose<br>
then ioError $ errnoToIOError "threadWait" eBADF Nothing Nothing<br>
else return ()<br>
<br>
I'm not sure this is semantically equivalent.<br>
<br>
GHC can pre-empt a thread whenever it allocates memory, and I assume<br>
it can deliver exceptions at that granularity too. So if<br>
`onException` allocates memory before the exception handler is set up,<br>
then an exception could possibly be delivered in that brief window,<br>
which would result in `unregisterFd_ mgr reg` never being called, and<br>
an exception being raised in the caller of `threadWait`.<br>
<br>
On Thu, 17 Jan 2019 at 22:43, Andrew Martin <<a href="mailto:andrew.thaddeus@gmail.com" target="_blank">andrew.thaddeus@gmail.com</a>> wrote:<br>
><br>
> Thanks. That makes sense. So, in the code I’m looking at, since takeMVar is the last effectful thing that happens, there is no semantic difference between having mask_ extend all the way down to the bottom of the block (as it currently does) and cutting it off right before the line involving takeMVar?<br>
><br>
> Sent from my iPhone<br>
><br>
> On Jan 17, 2019, at 5:23 PM, Michael Walker <<a href="mailto:mike@barrucadu.co.uk" target="_blank">mike@barrucadu.co.uk</a>> wrote:<br>
><br>
> >> Although the entire function has asynchronous exceptions masked, the call to takeMVar uses onException to deal with the possibility of an exception. According to the docs in Control.Concurrent, takeMVar can throw exceptions. But my understand (which may be wrong) is that the only exception this could throw would be something like BlockedIndefinitelyOnMVar, which I don't believe can happen here.<br>
> ><br>
> > That's not quite right. The mask_ function blocks asynchronous<br>
> > exceptions from being delivered to the thread while it's not<br>
> > "interruptible". Most blocking functions, such as takeMVar, make the<br>
> > thread interruptible while they're blocked. So any asynchronous<br>
> > exception (such as ThreadKilled) could be delivered to the thread if<br>
> > it blocks in the takeMVar.<br>
> ><br>
> > --<br>
> > Michael Walker (<a href="http://www.barrucadu.co.uk" rel="noreferrer" target="_blank">http://www.barrucadu.co.uk</a>)<br>
<br>
<br>
<br>
-- <br>
Michael Walker (<a href="http://www.barrucadu.co.uk" rel="noreferrer" target="_blank">http://www.barrucadu.co.uk</a>)<br>
_______________________________________________<br>
Libraries mailing list<br>
<a href="mailto:Libraries@haskell.org" target="_blank">Libraries@haskell.org</a><br>
<a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries" rel="noreferrer" target="_blank">http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries</a><br>
</blockquote></div>