<div dir="ltr"><div>Hi Lars,</div><div><br></div><div>uh, order issues are difficult for me.</div><div>Although this is not the answer, I write a little.</div><div><br></div><div>At first:</div><div>  "critical section" ... is block that should protect the invariants.</div><div>  "atomic block"     ... is undivided code block.</div><div><br></div><div>Your point (1) and (2) are "critical section" for mfd and fd,</div><div>but not "atomic block".</div><div><br></div><div>readMVar can't create "atomic block". It's only read the content of MVar.</div><div><br></div><div>Of cource, as you have said.</div><div>If point (1) have no memory allocations, </div><div>async exception and timer-based thread context switch don't occur there.</div><div>But you might think many other case, such as implement dependent.</div><div><br></div><div>If you want to protect the critical section exactly,<br></div><div>it is better to use an explicit mechanism rather than implicit mechanism.</div><div><br></div><div><br></div><div>Libraries on hackage[1] might be helpful.</div><div><br></div><div>For performance pursuit, there may be a gimmick way;-)</div><div><br></div><div>[1]: <a href="https://hackage.haskell.org/">https://hackage.haskell.org/</a></div><div><br></div><div>Cheers,<br></div><div>Takenobu</div><div><br></div><div><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">2015-05-22 20:55 GMT+09:00 Lars Petersen <span dir="ltr"><<a href="mailto:info@lars-petersen.net" target="_blank">info@lars-petersen.net</a>></span>:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hello cafe,<br>
<br>
I'm currently trying to understand Haskell's threading model and GHC's<br>
implementation of it. Specifically I wondered about the safety of file<br>
IO. Consider this piece of code:<br>
<br>
> newtype Socket = Socket (MVar Fd)<br>
><br>
> read :: Socket -> IO ByteString<br>
> read (Socket mfd) = do<br>
>   fd <- readMVar mfd<br>
>   -- (1)<br>
>   threadWaitRead fd<br>
>   -- (2)<br>
>   withMVar mfd $ \fd'-> do<br>
>     -- (3) the actual read...<br>
<br>
Context:<br>
  - The socket is configured non-blocking.<br>
  - No other operation will hold the MVar over a blocking call (because<br>
this would make it impossible to close it while it's blocking).<br>
  - My close operation will fill the MVar with -1 after it's closed and<br>
will hold the MVar during the close operation.<br>
<br>
Questions:<br>
  - Is it theoretically possible that my thread gets paused at (1) or<br>
within threadWaitRead, another thread closes the socket (or even worse<br>
opens another file with the same fd) _and_ my thread is resumed<br>
afterwards (I'm not asking about async exceptions)?<br>
  - What constructs contain safepoints and which are guaranteed to be<br>
executed without interruption?<br>
<br>
Considerations (so far):<br>
  - It is unlikely that (1) is a safepoint as no memory allocations<br>
occur, but is it guaranteed?<br>
  - If the socket were closed during (1), threadWaitRead throws an<br>
exception complaining about a bad file descriptor which is unexpected<br>
but not harmful.<br>
  - I found this thread<br>
(<a href="https://mail.haskell.org/pipermail/haskell-cafe/2014-September/115841.html" target="_blank">https://mail.haskell.org/pipermail/haskell-cafe/2014-September/115841.html</a>)<br>
which is somewhat related, but I couldn't extract a clear answer from it.<br>
<br>
Best,<br>
  Lars<br>
<br>
<br>
<br>
_______________________________________________<br>
Haskell-Cafe mailing list<br>
<a href="mailto:Haskell-Cafe@haskell.org">Haskell-Cafe@haskell.org</a><br>
<a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe" target="_blank">http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe</a><br>
</blockquote></div><br></div>